5286. 網格中的最短路徑--Leecode刷題

周賽的時候的題目:每次周賽基本上第四道題都做不出來,除了感慨自己菜以外,還會感嘆那些做的很快的大佬,是真的很厲害了!!!

題目描述:

給你一個 m * n 的網格,其中每個單元格不是 0(空)就是 1(障礙物)。每一步,您都可以在空白單元格中上、下、左、右移動。

如果您 最多 可以消除 k 個障礙物,請找出從左上角 (0, 0) 到右下角 (m-1, n-1) 的最短路徑,並返回通過該路徑所需的步數。如果找不到這樣的路徑,則返回 -1。

示例 1:

輸入:
grid =
[[0,0,0],
[1,1,0],
[0,0,0],
[0,1,1],
[0,0,0]],
k = 1
輸出:6
解釋:
不消除任何障礙的最短路徑是 10。
消除位置 (3,2) 處的障礙後,最短路徑是 6 。該路徑是 (0,0) -> (0,1) -> (0,2) -> (1,2) -> (2,2) -> (3,2) -> (4,2).

示例 2:

輸入:
grid =
[[0,1,1],
[1,1,1],
[1,0,0]],
k = 1
輸出:-1
解釋:
我們至少需要消除兩個障礙才能找到這樣的路徑。

分析:

首先這題我開始的思路是這樣,記錄每個位置不消除障礙物的最短路徑,消除一個障礙物的最短路徑,消除兩個障礙物的最短路徑…消除k個障礙物的最短路徑,所以需要構造 dp[row] [col] [k] 來記錄,看這個結構就知道,這是一個動態規劃的問題,但是問題是,怎麼訪問各個點的最短路徑,從上到下?從左到右?我很蒙。

方法:動態規劃+DBS

用一個隊列(爲啥不用棧,到最後說明),首先放入的是dp[0][0][0]的值爲0,之後更新上下左右dp[gx][gy][k],但是注意!!!
首先,只有當dp[gx][gy][k]爲-1的時候才需要更新,因爲如果已經有值一定是之前更新了的,那麼之前更新的步數應該是比當前更新的步數要小的。
第二個問題,當更新的值位置的值
當前位置爲grid[gx][gy] == 0時,那麼k = a.k(就是從隊列出來的k值)
當前位置爲grid[gx][gy] == 1時,那麼k= a.k+1,因爲你當前爲1要想到達當前位置,必須消除當前的障礙!!!
之後入隊。
這裏說明一個問題:這裏存在着一個循環,就是你更新下面一個結點(這個結點grid[i][j] = 1)之後,入隊,取出,你又更新上面的值,看起來好像是循環了,但是用一個條件,就是你的k是有限的!!!這樣只會更新到k,超過k就不做更新,就不會入隊循環了!!!

代碼如下:

struct node{
    int x,y,k;
    node() {}
    node(int _x,int _y,int _k) { x=_x; y=_y; k=_k; }
};
class Solution {
public:

    int shortestPath(vector<vector<int>>& grid, int k) {

        queue<node> q;
            int row=grid.size();
            int col=grid[0].size();
            int x[4] = {0,0,1,-1};
            int y[4] = {1,-1,0,0};

            int dp[row][col][k+1];
            memset(dp, -1, sizeof(dp));
        dp[0][0][0] = 0;
            q.push(node(0,0,0));

            while(!q.empty()){
                node a = q.front();
                q.pop();

                for(int i = 0;i < 4;i++){
                    int gx = a.x+x[i];
                    int gy = a.y+y[i];
                    if(gx >= 0&&gx < row&&gy >= 0&&gy < col&&a.k+grid[gx][gy] <= k){
                        if(dp[gx][gy][a.k+grid[gx][gy]] == -1){
                            dp[gx][gy][a.k+grid[gx][gy]] = dp[a.x][a.y][a.k]+1;
                            q.push(node(gx,gy,a.k+grid[gx][gy]));
                        }
                    }
                }
            }

            int ans = dp[row-1][col-1][0];
            for(int i = 1;i <= k;i++){
                ans = min(ans,dp[row-1][col-1][i]);
            }
            return ans;
    }
};


這題讓我思考了一類題:
1.矩陣
2.每個點具有不同條件下的狀態(k不同)
3.且是由上下左右影響,即每個點變化都會影響周圍點的變化

解決方法:動態規劃+DBS+隊列(剛纔不懂爲啥要用隊列現在想想好像是的!!!,因爲保證每次更新都是最小值,且下次不用更新了!!!)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章