打印路径可以用栈的方式, 也可以用递归。
下面看看用递归做的吧
还是NYOJ 最少步数那道题
#include <iostream>
#include<queue>
#include<cstring>
#include<cstdio>
const int dx[4] = {0, 0,-1, 1};
const int dy[4] = {-1,1, 0, 0};
struct node
{
int x, y;
int step;
};
int x1, y1, x2, y2;
node now, next;
node S,E;
using namespace std;
bool vis[10][10];
node qq[10][10];
int map[9][9] = {1,1,1,1,1,1,1,1,1
, 1,0,0,1,0,0,1,0,1
,1,0,0,1,1,0,0,0,1
,1,0,1,0,1,1,0,1,1
,1,0,0,0,0,1,0,0,1
,1,1,0,1,0,1,0,0,1
,1,1,0,1,0,1,0,0,1
,1,1,0,1,0,0,0,0,1
,1,1,1,1,1,1,1,1,1};
int bfs()
{
if(S.x == E.x && S.y == E.y)
return 0;
memset(vis, false,sizeof(vis));
queue<node>q;
q.push(S);
vis[S.x][S.y] = true;
while(!q.empty())
{
now = q.front();
q.pop();
for(int i=0; i<4; i++)
{
next.x = now.x + dx[i];
next.y = now.y + dy[i];
next.step = now.step + 1;
if(map[next.x][next.y] == 1||next.x > 9 || next.x<0 || next.y>9 || next.y<0 || vis[next.x][next.y])
continue;
vis[next.x][next.y] = true;
qq[next.x][next.y].x = now.x;
qq[next.x][next.y].y = now.y;
q.push(next);
if(next.x == E.x && next.y == E.y)
return next.step;
}
}
return -1;
}
void pri(int sx, int sy) {
if( sx==x1 && sy==y1 ) {
printf("(%d, %d)\n", sx, sy);
return ;
}
pri(qq[sx][sy].x, qq[sx][sy].y);
printf("(%d, %d)\n", sx, sy);
}
int main()
{
int T;
cin >> T;
while(T--)
{
cin >> x1 >> y1;
cin >> x2 >> y2;
S.x = x1;
S.y = y1;
S.step = 0;
E.x = x2;
E.y = y2;
int ans = bfs();
if(ans >= 0)
{
cout << ans << endl;
pri(x2, y2);
}
}
return 0;
}
下面是用栈实现的:
#include <iostream>
#include<queue>
#include<cstring>
#include<stack>
const int dx[4] = {0, 0,-1, 1};
const int dy[4] = {-1,1, 0, 0};
struct node
{
int x, y;
int step;
};
int x1, y1, x2, y2;
node now, next;
node S,E;
node Pre[10][10];
using namespace std;
bool vis[10][10];
int map[9][9] = {1,1,1,1,1,1,1,1,1
, 1,0,0,1,0,0,1,0,1
,1,0,0,1,1,0,0,0,1
,1,0,1,0,1,1,0,1,1
,1,0,0,0,0,1,0,0,1
,1,1,0,1,0,1,0,0,1
,1,1,0,1,0,1,0,0,1
,1,1,0,1,0,0,0,0,1
,1,1,1,1,1,1,1,1,1};
int bfs()
{
if(S.x == E.x && S.y == E.y)
return 0;
memset(vis, false,sizeof(vis));
queue<node>q;
q.push(S);
vis[S.x][S.y] = true;
while(!q.empty())
{
now = q.front();
q.pop();
for(int i=0; i<4; i++)
{
next.x = now.x + dx[i];
next.y = now.y + dy[i];
next.step = now.step + 1;
if(map[next.x][next.y] == 1||next.x > 9 || next.x<0 || next.y>9 || next.y<0 || vis[next.x][next.y])
continue;
vis[next.x][next.y] = true;
Pre[next.x][next.y] = now;
q.push(next);
if(next.x == E.x && next.y == E.y)
return next.step;
}
}
return -1;
}
void PrintPath(int row,int column){
//输出最短路径
node temp; //保存位置
stack<node> s; //保存路径序列
temp.x = row;
temp.y = column;
while(temp.x != x1 || temp.y != y1){
s.push(temp);
temp = Pre[temp.x][temp.y];
}
cout<<"(" << x1 << "," << y1 << ")" << endl;
while(!s.empty()){
temp = s.top();
cout<<"("<<temp.x<<","<<temp.y<<")" << endl;
s.pop();
}
cout<<endl;
}
int main()
{
int T;
cin >> T;
while(T--)
{
cin >> x1 >> y1;
cin >> x2 >> y2;
S.x = x1;
S.y = y1;
S.step = 0;
E.x = x2;
E.y = y2;
int ans = bfs();
if(ans >= 0)
{
cout << ans << endl;
PrintPath(x2, y2);
}
}
return 0;
}
/*
2
3 1 5 7
12
(3,1)
(4,1)
(4,2)
(4,3)
(4,4)
(5,4)
(6,4)
(7,4)
(7,5)
(7,6)
(7,7)
(6,7)
(5,7)
3 1 6 7
11
(3,1)
(4,1)
(4,2)
(4,3)
(4,4)
(5,4)
(6,4)
(7,4)
(7,5)
(7,6)
(7,7)
(6,7)
Process returned 0 (0x0) execution time : 24.583 s
Press any key to continue.
*/
再做做下面这道题, 越来越发现应该学会融会贯通啊!
题目描述:
一个网格迷宫由n行m列的单元格组成,每个单元格要么是空地(用1表示),要么是障碍物(用0来表示)。你的任务是找一条从起点到终点的最短步数和移动序列,其中UDLR表示上下左右操作。任何时候都不能在障碍物格子中,也不能走到迷宫之外。起点和终点保证都是空地。n,m<100。
样例输入:
6 5
11011
10111
10100
10111
11101
11111
样例输出:
9
DDDDDRRRR
解题思路:
较上一个文章来说,只是多了输出路径,这里既然题目没规定入口出口,为了方便起见,我人为的把入口和出口规定为左上角和右下角。记录路径即需要知道终点是由那个点走到的,而这个点的上一个点也需要知道……所以就记录下每个点的父节点和相应的操作,然而准备输出路径的时候又遇到了一个问题:从出口一步步向上寻找,是一个倒着的,怎么才能正着输出呢?先进后出这个特点是栈对应的特点,而递归类似栈,所以利用递归的方式,达到按顺序输出的目的。
代码:
- #include<cstdio>
- #include<queue>
- #include<iostream>
- using namespace std;
- char mmap[10][10]={};
- int vis[10][10]={};
- int n,m;
- int xx[4]={1,0,0,-1};
- int yy[4]={0,1,-1,0};
- struct node
- {
- int x,y;
- int t;
- };
- struct father
- {
- int x,y;//当前格子的父节点坐标
- char cz;//由什么操作到达的这个格子
- };
- queue<node> q;
- node s,f;
- father lj[10][10];//记录路径
- int bfs()
- {
- int i,j;
- s.x=0;s.y=0;s.t=0;
- f.x=n-1;f.y=m-1;
- q.push(s);
- lj[s.x][s.y].x=1000;//因为m,n<=100
- lj[s.x][s.y].y=1000;
- lj[s.x][s.y].cz=0;
- vis[s.x][s.y]=1;//标为已经访问过
- while(!q.empty())
- {
- node now=q.front();
- q.pop();
- for(i=0;i<4;++i)
- {
- node New;
- New.x=now.x+xx[i];
- New.y=now.y+yy[i];
- New.t=now.t+1;
- if(New.x<0||New.y<0||New.x>=n||New.y>=m||vis[New.x][New.y]||mmap[New.x][New.y]=='0')//下标越界或者访问过或者是障碍物
- continue;
- q.push(New);
- lj[New.x][New.y].x=now.x;
- lj[New.x][New.y].y=now.y;
- if(i==0) lj[New.x][New.y].cz='D';
- else if(i==1) lj[New.x][New.y].cz='R';
- else if(i==2) lj[New.x][New.y].cz='L';
- else if(i==3) lj[New.x][New.y].cz='U';
- vis[New.x][New.y]=1;
- if(New.x==f.x&&New.y==f.y) return New.t;//到达终点
- }
- }
- return -1;
- }
- void dfs(int x, int y)
- {
- if(x==0&&y==0) return;//找到父节点是起点的格子了
- else
- dfs(lj[x][y].x,lj[x][y].y);
- printf("%c",lj[x][y].cz);
- }
- int main()
- {
- int i,j,ans;
- scanf("%d%d",&n,&m);
- for(i=0;i<n;++i)
- {
- scanf("%s",mmap[i]);
- }
- ans=bfs();
- if(ans<0) printf("error");
- else
- {
- printf("%d\n",ans);
- dfs(n-1,m-1);//从终点开始找他的父节点
- }
- return 0;
- }