广度优先搜索——20191223

3、 leetcode 1293.网格中的最短路径
3.1 题目描述
给你一个 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
解释:
我们至少需要消除两个障碍才能找到这样的路径。

提示:
grid.length == m
grid[0].length == n
1 <= m, n <= 40
1 <= k <= m*n
grid[i][j] == 0 or 1
grid[0][0] == grid[m-1][n-1] == 0
3.2 分析
对于二维网格中的最短路问题,我们一般可以使用广度优先搜索 + 队列的方法解决。这样我们就可以使用三元组 (x, y, rest) 表示一个搜索状态,其中 (x, y) 表示玩家的位置,rest 表示玩家还可以经过 rest 个障碍物。
//visit取值:-1 表示未访问过;0表示访问过,剩余0次可以消除;1表示访问过,剩余1次可以消除;以此类推
3.3 代码
typedef struct {
int i;
int j;
int cnt;
} PathNode;

typedef struct {
PathNode* head;
int front;
int tail;
} PathQueue;

void InitQueue(PathQueue * queue, int max) {
if(queue == NULL) {
return;
}
queue->head = (PathNode*)malloc(sizeof(PathNode) * max);
if(queue->head == NULL) {
return;
}
queue->front = 0;
queue->tail = 0;
}

void DestroyQueue(PathQueue * queue) {
if(queue != NULL) {
free(queue->head);
queue->head = NULL;
queue->front = 0;
queue->tail = 0;
}
}

void EnQueue(PathQueue * queue, PathNode node, int max) {
if((queue->tail + 1) % max == queue->front) {//超了
return;
}
queue->head[queue->tail] = node;
queue->tail = (queue->tail + 1) % max;
}

PathNode DeQueue(PathQueue * queue, int max) {
PathNode result = queue->head[queue->front];
queue->front = (queue->front + 1) % max;
return result;
}

//visit取值:-1 表示未访问过;0表示访问过,剩余0次可以消除;1表示访问过,剩余1次可以消除;以此类推
int shortestPath(int** grid, int gridSize, int* gridColSize, int k){
int i = 0, j = 0, m = 0;
int result = -1;
PathNode tmpNode, tmpNode2;
int max = gridSize * (*gridColSize) + 100;
int mData[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

//初始化visit
int visit[gridSize][*gridColSize];
memset(visit, -1, sizeof(visit));

//初始化queue,以及首节点
PathQueue* queue = (PathQueue*)malloc(sizeof(PathQueue));
if(queue == NULL) {
    return -1;
}
InitQueue(queue, max);
visit[0][0] = k;
tmpNode.i = 0;
tmpNode.j = 0;
tmpNode.cnt = 0;
if(grid[0][0] == 1) {
    if(k <= 0) {
        return -1;
    }
    else {
        visit[0][0] = k - 1;
    }
}

EnQueue(queue, tmpNode, max);

while(queue->front != queue->tail) {
    tmpNode2 = DeQueue(queue, max);
    if(tmpNode2.i == gridSize - 1 && tmpNode2.j == *gridColSize - 1) {
        result = tmpNode2.cnt;
        break;
    }

    //四个方向遍历
    for(m = 0; m < 4; m++) {
        if((tmpNode2.i + mData[m][0]) < 0 || (tmpNode2.i + mData[m][0]) >= gridSize || (tmpNode2.j + mData[m][1]) < 0 || (tmpNode2.j + mData[m][1]) >= *gridColSize) {
            continue;
        }

        tmpNode.i = tmpNode2.i + mData[m][0];
        tmpNode.j = tmpNode2.j + mData[m][1];
        tmpNode.cnt = tmpNode2.cnt + 1;

        if(visit[tmpNode.i][tmpNode.j] < 0) {//未访问过
            if(grid[tmpNode.i][tmpNode.j] == 0) {//无障碍
                visit[tmpNode.i][tmpNode.j] = visit[tmpNode2.i][tmpNode2.j];
                EnQueue(queue, tmpNode, max);
            }
            else {//有障碍
                if(visit[tmpNode2.i][tmpNode2.j] > 0) {//有剩余的k
                    visit[tmpNode.i][tmpNode.j] = visit[tmpNode2.i][tmpNode2.j] - 1;
                    EnQueue(queue, tmpNode, max);
                }
            }
        }
        else {//访问过
            if(grid[tmpNode.i][tmpNode.j] == 0) {//无障碍
                if(visit[tmpNode2.i][tmpNode2.j] > visit[tmpNode.i][tmpNode.j]) {//有更多的k
                    visit[tmpNode.i][tmpNode.j] = visit[tmpNode2.i][tmpNode2.j];
                    EnQueue(queue, tmpNode, max);
                }
            }
            else {//有障碍
                if(visit[tmpNode2.i][tmpNode2.j] > 0) {//有剩余的k
                    if((visit[tmpNode2.i][tmpNode2.j] - 1) > visit[tmpNode.i][tmpNode.j]) {//有更多的k
                        visit[tmpNode.i][tmpNode.j] = visit[tmpNode2.i][tmpNode2.j] - 1;
                        EnQueue(queue, tmpNode, max);
                    }
                }
            }
        }
    }
}

DestroyQueue(queue);
free(queue);
queue = NULL;

return result;

}

发布了39 篇原创文章 · 获赞 1 · 访问量 856

猜你喜欢

转载自blog.csdn.net/weixin_42268479/article/details/103662730