5 6 .XX.1. ..X.2. 2...X. ...XX. XXXXX. 5 6 .XX.1. ..X.2. 2...X. ...XX. XXXXX1 5 6 .XX... ..XX1. 2...X. ...XX. XXXXX.
It takes 13 seconds to reach the target position, let me show you the way. 1s:(0,0)->(1,0) 2s:(1,0)->(1,1) 3s:(1,1)->(2,1) 4s:(2,1)->(2,2) 5s:(2,2)->(2,3) 6s:(2,3)->(1,3) 7s:(1,3)->(1,4) 8s:FIGHT AT (1,4) 9s:FIGHT AT (1,4) 10s:(1,4)->(1,5) 11s:(1,5)->(2,5) 12s:(2,5)->(3,5) 13s:(3,5)->(4,5) FINISH It takes 14 seconds to reach the target position, let me show you the way. 1s:(0,0)->(1,0) 2s:(1,0)->(1,1) 3s:(1,1)->(2,1) 4s:(2,1)->(2,2) 5s:(2,2)->(2,3) 6s:(2,3)->(1,3) 7s:(1,3)->(1,4) 8s:FIGHT AT (1,4) 9s:FIGHT AT (1,4) 10s:(1,4)->(1,5) 11s:(1,5)->(2,5) 12s:(2,5)->(3,5) 13s:(3,5)->(4,5) 14s:FIGHT AT (4,5) FINISH God please help our poor hero. FINISH
解题思路:用的bfs宽度优先搜索框架,本题的难点就是不光需要求出最短距离,还要打印出最短路径。昨天折腾了几个小时,用的传统的BFS,结果测试数据对,但提交一直Wa,在网上找了一些测试数据,结果没通过,发现了自己代码中的问题,要用到优先队列,于是我修改自己的代码把原来的队列换成优先队列,结果改完后测试数据和没改之前一模一样,一直到晚上睡觉前也没弄出来。今天早上早起又把代码仔细看了一遍,终于发现问题了,代码中优先队列的优先级竟然没有值,我说怎么用不用都一个样呢,又改了几个地方,提交竟然通过了。哎,看来,一道题目长时间做不出来还得先放一放沉淀一下。路径保存用二维数组,数组中的每个元素都是一个结构体类型的节点,里面起关键作用的就是fx,fy,前一个节点到当前节点的x增量和y增量,打印的时候用递归,回溯。
代码:
#include <iostream> #include <queue> #include <string.h> using namespace std; char map[102][102]; //地图 bool visited[102][102];//判断是否访问 int Min; int dx[4]={0,0,-1,1};//方向控制 int dy[4]={-1,1,0,0}; struct node //每个坐标是一个节点 { int x,y;//坐标位置 int fx,fy;//增量比如前一个节点的x+1得到当前节点的x值,fx就为1 ,这在后面记录路径时用到 int step; bool operator<(const node t)const{//后面用到了优先队列,对<进行重载,队列中step小的node在队头 top()。 return step>t.step; } }; node path[102][102];//用来记录路径,因为队列中的node都pop掉了,所以用一个数组来保存路径。 node a,b,c;//临时变量 int N,M;//地图大小 void getmap()//输入地图 { for(int i=0;i<N;++i) for(int j=0;j<M;++j) cin>>map[i][j]; } void print(int n,int m)//打印路径,用递归的形式 { if(n==0&&m==0) return; print(n-path[n][m].fx,m-path[n][m].fy); if(map[n][m]>='1'&&map[n][m]<='9') { int t=map[n][m]-'0'; cout<<path[n][m].step-t<<"s:"<<"("<<n-path[n][m].fx<<","<<m-path[n][m].fy<<")->("<<n<<","<<m<<")"<<endl; while(t) { cout<<path[n][m].step-t+1<<"s:"<<"FIGHT AT ("<<n<<","<<m<<")"<<endl; t--; } } else cout<<path[n][m].step<<"s:"<<"("<<n-path[n][m].fx<<","<<m-path[n][m].fy<<")->("<<n<<","<<m<<")"<<endl; } int main() { while(cin>>N>>M) { memset(visited,0,sizeof(visited)); priority_queue <node>q;//优先队列,优先级为node中的step大小 getmap(); a.x=0; a.y=0; a.fx=0; a.fy=0; a.step=0; visited[0][0]=1;//坐标(0,0)处开始 q.push(a); path[0][0]=a; while(!q.empty()) { b=q.top(); q.pop(); if(b.x==N-1&&b.y==M-1) { break; } for(int i=0;i<4;++i) { c.x=b.x+dx[i]; c.y=b.y+dy[i]; c.fx=dx[i]; c.fy=dy[i]; if(c.x>=0&&c.x<N&&c.y>=0&&c.y<M&&map[c.x][c.y]!='X'&&!visited[c.x][c.y]) { path[c.x][c.y]=c; visited[c.x][c.y]=1;//已访问 if(map[c.x][c.y]>='1'&&map[c.x][c.y]<='9') { path[c.x][c.y].step=path[b.x][b.y].step+map[c.x][c.y]-'0'+1; c.step=b.step+map[c.x][c.y]-'0'+1;//这条语句很重要啊,一开始就是忘了写这条语句,结果优先队列使用和不使用一个样,队列中的node的step起关键作用,不能忘 } else { path[c.x][c.y].step=path[b.x][b.y].step+1; c.step=b.step+1; } q.push(c);//注意这句不能提前写,要保证,节点c中德各个元素都有值,x,y,fx,fy,step } } } /* for(int i=0;i<N;++i) { for(int j=0;j<M;j++) cout<<step[i][j]<<" "; cout<<endl; }*/ //用来测试步数 if(visited[N-1][M-1])//如果目的地坐标(N-1,M-1)被访问了,说明可以到达目的地 { cout<<"It takes "<<path[N-1][M-1].step<<" seconds to reach the target position, let me show you the way."<<endl; print(N-1,M-1); } else cout<<"God please help our poor hero."<<endl; cout<<"FINISH"<<endl; } return 0; }
上面是题目上给的测试数据,但是很坑啊,你以为代码写对了,其实没对,我就掉进坑里了,一直Wrong Answer于是在网上又找测试数据,发现下面一组,
5 7
...X...
.X.X.X.
.X...X.
.XXXXX.
....9..
正确结果应该是14s,我原来的代码结果是19s,所以一直错。修改后的代码运行结果: