Time Limit: 1sec Memory Limit:256MB
Description
有一个矩形迷宫,入口和出口都确定为唯一的,且分布在矩形的不同边上。 现在让你算出最短需要走多少步,才可以从入口走到出口。
Input
共N+1行,第一行为N(N=0表示输入结束),以下N行N列0-1矩阵,1表示不能通过,0表示可以通过 (左上角和右下角为0,即入口和出口),其中N<30。
Output
只有一个数,为最少要走的格子数。0表示没有路径。 Sample Input 5 0 1 1 1 1 0 0 1 1 1 1 0 0 0 1 1 1 1 0 1 1 1 1 0 0 4 0 0 1 1 0 0 0 1 1 1 1 1 1 1 1 0 0 Sample Output 9 0 |
这题也是道搜索题,求最小步数,要用广度优先搜索。同时也包含状态转换(每到一个地图点,不计合法与否,下一步有四个方向可以转换)。
那么问题来了,怎样判重从而减少时间、去除路径死循环呢?像魔板那道题一样用一个visit二维数组标记就可以了。
广搜就用队列。如果把这道题想象成一棵以初始状态为根,以合法状态转换为边,以同时生成的新状态为子树的多叉树,那么很容易理解广搜实际上是按层次遍历节点。如果从根节点开始的路径p1与p2,有p1短于p2,且两条路径都可到达同一地图点N(设二者对应的最终状态节点分别为S1和S2),那么在这颗树中,S1节点必定会在S2节点之前被遍历到。
不知道是这玩意儿是只可意会不可言传,还是我表达能力捉急,反正就这样~
以下是代码和注释:
#include<iostream>
#include<queue>
#define MAX 31
using namespace std;
// 上下左右四个方向
int dirX[] = { 0, 0, -1, 1 };
int dirY[] = { -1, 1, 0, 0 };
// 路径节点
struct node{
int x; // 当前点的x坐标
int y; // 当前点的y坐标
int step; // 到达当前点后,已走过的步数
node() {}
node(int _x, int _y, int _s) : x(_x), y(_y), step(_s) {}
};
void bfsSearch(queue<node>& q, bool map[][MAX], bool visit[][MAX], int n, bool& isOK) {
while ( !q.empty() && !isOK ) {
node t = q.front();
q.pop();
// 到达终点
if (t.x == n - 1 && t.y == n - 1) {
isOK = true;
cout << t.step << endl;
break;
}
// 上下左右四个方向
for (int i = 0; i < 4; i++) {
int nextX = t.x + dirX[i];
int nextY = t.y + dirY[i];
// 判断是否出界、可达
if (nextX < 0 || nextY < 0 || nextX >= n || nextY >= n || map[nextX][nextY])
continue;
// 若已访问过则不重复前往该点;否则建造新的路径节点并入队列
if (!visit[nextX][nextY]) {
visit[nextX][nextY] = 1;
q.push(node(nextX, nextY, t.step + 1));
}
}
}
}
int main() {
int n;
bool map[MAX][MAX];
bool visit[MAX][MAX]; // 用于判重
cin >> n;
while (n!=0) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cin >> map[i][j];
visit[i][j] = 0;
}
}
queue<node> q;
// 根节点先入队
q.push(node(0, 0, 1));
bool isOK = false;
bfsSearch(q, map, visit, n, isOK);
if (!isOK)
cout << "0\n";
cin >> n;
}
return 0;
}
/* TEST CASES
5
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0
---9
5
0 1 0 0 0
0 1 0 1 0
0 0 1 0 0
0 1 1 1 0
0 0 0 1 0
---0
5
0 1 0 0 0
0 1 0 1 0
0 1 1 0 0
0 0 0 1 0
0 0 0 1 0
---0
5
0 1 0 0 0
0 1 0 1 0
0 1 0 1 0
0 1 0 1 0
0 0 0 1 0
---17
0
*/