Description
定义一个二维数组:
int maze[5][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,
};
它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。
Input
一个5 × 5的二维数组,表示一个迷宫。数据保证有唯一解。
Output
左上角到右下角的最短路径,格式如样例所示。
Sample Input
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
Sample Output
(0, 0)
(1, 0)
(2, 0)
(2, 1)
(2, 2)
(2, 3)
(2, 4)
(3, 4)
(4, 4)
在实现保存路径的时候没有太好的方法,用了一个数组来存每个坐标的前驱,最后从终点开始向前推,并将路径逆向存入一个数组,最后输出,还要补上(4,4)
其实可以用一个栈来保存的,从终点开始压入栈,最后再依次出栈。
#include<stdio.h>
#include<queue>
#include<string.h>
#include<utility>
using namespace std;
const int inf=0x3f3f3f3f;
int m[5][5];//迷宫
int d[5][5];//距离
typedef pair<int,int> P;
queue<P> q;//储存坐标
P arr[5][5];//用来保存每个坐标的前驱
int a[4]={-1,1,0,0};//移动
int b[4]={0,0,-1,1};
void bfs(int x,int y)
{
q.push(P(x,y));//起点
d[x][y]=0;//起点到起点距离
int dx,dy;//移动后的坐标
while(q.size())//当队列取完后结束
{
pair<int,int> p=q.front(); q.pop();//取队列中的坐标
if(p.first==4&&p.second==4)//到达终点,结束,返回到终点的距离
break;
for(int i=0;i<5;i++)//遍历出达到的坐标
{
dx=p.first+a[i];//在上一个坐标的基础上改变
dy=p.second+b[i];
if(dx>=0&&dx<5&&dy>=0&&dy<5&&m[dx][dy]==0&&d[dx][dy]==inf)
{
q.push(P(dx,dy));//将能到达的坐标放入队列
d[dx][dy]=d[p.first][p.second]+1;
arr[dx][dy]=p;
}
}
}
}
int main()
{
arr[0][0]=make_pair(0,0);
memset(d,inf,sizeof(d));//初始化为无穷大
for(int i=0;i<5;i++)
for(int j=0;j<5;j++)
scanf("%d",&m[i][j]);
bfs(0,0);
P arr2[100];//翻转arr,得到arr2
int a=4,b=4;
for(int i=d[4][4]-1;i>=0;i--)
{
arr2[i]=arr[a][b];
a=arr2[i].first;
b=arr2[i].second;
}
for(int i=0;i<d[4][4];i++)
printf("(%d, %d)\n",arr2[i].first,arr2[i].second);
printf("(4, 4)\n");
return 0;
}
因为上面那个方法不太好,又重新写了一个用栈来实现的做法。
一开始因为没有把起点压入队列而是压入了栈,导致了错误,汗。。。
还有定义了bfs()函数忘了去使用。。。
最后用栈的时候终止条件是到达了(0,0),我们上一步的pre就是(0,0),已经被压入栈了。
#include<stdio.h>
#include<iostream>
#include<stack>
#include<queue>
#include<string.h>
using namespace std;
typedef pair<int,int> p;
p a;
queue<p> q;
stack<p> s;
int m[5][5];
bool vis[5][5];
p pre[5][5];
int h[]={1,-1,0,0};
int l[]={0,0,1,-1};
void bfs()
{
q.push(p(0,0));
vis[0][0]=1;
while(q.size())
{
a=q.front();q.pop();
for(int i=0;i<4;i++)
{
int nx=a.first+h[i];
int ny=a.second+l[i];
if(nx>=0&&nx<=4&&ny>=0&&ny<=4&&vis[nx][ny]==0&&m[nx][ny]==0)
{
q.push(p(nx,ny));
vis[nx][ny]=1;
pre[nx][ny]=p(a.first,a.second);
}
}
}
}
int main()
{
for(int i=0;i<5;i++)
for(int j=0;j<5;j++)
scanf("%d",&m[i][j]);
memset(vis,0,sizeof vis);
bfs();
int x=4,y=4;
s.push(p(4,4));
while(x!=0||y!=0)
{
a=pre[x][y];
s.push(p(a));
x=a.first;
y=a.second;
}
while(s.size())
{
a=s.top();s.pop();
printf("(%d, %d)\n",a.first,a.second);
}
return 0;
}
第二次做的代码
这次错的也很离谱,bfs()中忘了压入队列
#include<stdio.h>
#include<queue>
#include<stack>
using namespace std;
typedef pair<int,int> p;
p a;
queue<p> q;
int m[5][5];
bool vis[5][5];
p pre[5][5];
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
stack<p> s;
void bfs()
{
q.push(p(0,0));
while(q.size())
{
a=q.front();q.pop();
if(a.first==4&&a.second==4)
break;
for(int i=0;i<4;i++)
{
int nx=a.first+dx[i];
int ny=a.second+dy[i];
if(nx>=0&&nx<5&&ny>=0&&ny<5&&m[nx][ny]==0&&vis[nx][ny]==0)
{
q.push(p(nx,ny));
vis[nx][ny]=1;
pre[nx][ny]=p(a.first,a.second);
}
}
}
}
int main(void)
{
for(int i=0;i<5;i++)
for(int j=0;j<5;j++)
scanf("%d",&m[i][j]);
bfs();
s.push(p(4,4));
p b=pre[4][4];
while(b.first!=0||b.second!=0)
{
s.push(b);
b=pre[b.first][b.second];
}
s.push(p(0,0));
while(s.size())
{
b=s.top();s.pop();
printf("(%d, %d)\n",b.first,b.second);
}
return 0;
}
目前我会的最简单的解法
dfs,设置一个变量flag,当走到终点后将flag设为1,如果flag是1,后面所有的递归调用都立即返回
如果没有这一步,后面的操作会对数组里的内容进行修改
或者,直接用vis来记录哪里走过了,最后直接循环遍历即可。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int ma[10][10];
typedef pair<int, int> P;
P arr[10];
bool vis[10][10], flag;
int dx[] = {0, 0, 1, -1}, dy[] = {1, -1, 0, 0};
void dfs(int x, int y, int state)
{
if (x == 4 && y == 4) {
printf("(0, 0)\n");
for (int i = 0; i < 8; i++) {
printf("(%d, %d)\n", arr[i]);
}
flag = 1;
return;
}
for (int i = 0; i < 4; i++) {
// 当走到终点后,立即返回,否则后面的操作会对数组造成修改
if (flag == 1) {
return;
}
int nx = x + dx[i], ny = y + dy[i];
if (nx >= 0 && nx < 5 && ny >= 0 && ny < 5 && vis[nx][ny] == 0 && ma[nx][ny] == 0) {
vis[nx][ny] = 1;
arr[state] = P(nx, ny);
dfs(nx, ny, state + 1);
vis[nx][ny] = 0;
}
}
}
int main(void)
{
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
cin >> ma[i][j];
}
}
vis[0][0] = 1;
dfs(0, 0, 0);
return 0;
}