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
题意:题意大致就是找从最左上角A[0,0]走到最右下角A[n-1][m-1]的最短带权路径.求最短路径一般基于BFS,本来打算用Dijkstra算法做.但是,这道题的输出要求很苛刻,貌似这是HDU的风格,输出要求一般比较苛刻.但是思路一样是基于BFS. 我们把图的每一个结点保存当前坐标(x,y),当前结点后继坐标(nextX,nextY),当前字符cc,当前最短权重time.从最末终的结点开始宽度优先搜索,一层一层往外扩,直到搜索完成,就可以生成一棵倒序的宽度优先搜索树,A[n-1][m-1]结点为树根,而A[0][0]为树叶,只要找从A[0][0]到A[n-1][m-1]的路径即为带树最短路径.
BFS思路明了.但是细节决定成败,真是WA了好多次.
#include<iostream> #include<queue> #include<limits.h> using namespace std; int n, m; struct node { char cc; int x;//当前坐标 int y; int nextX;//后继坐标 int nextY; int time; }; int dir[4][2]={{0,1},{0,-1},{-1,0},{1,0}}; //4方向 node map[105][105]; void outPut()//吭爹的output { int x=0,y=0,a,b,time=1,i; if(map[0][0].time!= INT_MAX) { printf("It takes %d seconds to reach the target position, let me show you the way.\n",map[0][0].time); while(x!= n-1|| y!=m-1) { a=map[x][y].nextX; b=map[x][y].nextY; if(map[x][y].cc!='.') for(i=0;i<map[x][y].cc - '0';i++) printf("%ds:FIGHT AT (%d,%d)\n",time++,x,y); printf("%ds:(%d,%d)->(%d,%d)\n",time++,x,y,a,b); x=a; y=b; } if(map[x][y].cc!='.') { for(i=0;i<map[x][y].cc - '0';i++) printf("%ds:FIGHT AT (%d,%d)\n",time++,x,y); } printf("FINISH\n"); } else { printf("God please help our poor hero.\nFINISH\n"); } } void BFS() { map[n-1][m-1].time=0; queue<node> Q; node qhead; int newPathLen=0; if( map[n-1][m-1].cc >='1' && map[n-1][m-1].cc <='9')//当前结点符号是数值,从终于开始搜索 map[n-1][m-1].time=map[n-1][m-1].cc-'0'; Q.push(map[n-1][m-1]); while(!Q.empty()) { qhead=Q.front(); Q.pop(); for(int i=0;i<4;++i)//4 direction { int tx=qhead.x+dir[i][0],ty=qhead.y+dir[i][1];//(tx,ty)是新坐标 if( tx < 0 || ty <0 ||tx>=n || ty >= m || map[tx][ty].cc =='X' )//新坐标在图外或者是X continue; if( map[tx][ty].cc != '.')//如果是数值,则权值+1,进一步要+1 newPathLen =map[tx][ty].cc-'0' + qhead.time ;//如果不是数值,权值不变 else newPathLen = qhead.time ;//如果新的路径比原路径更短,更新之 if( newPathLen+1 < map[tx][ty].time) { map[tx][ty].time=newPathLen+1; map[tx][ty].nextX = qhead.x; map[tx][ty].nextY = qhead.y; Q.push(map[tx][ty]); } } } outPut(); } int main() { while(cin>>n>>m) { for(int i=0;i<n;++i) { for(int j=0;j<m;++j) { cin>>map[i][j].cc; map[i][j].time=INT_MAX; map[i][j].x=i; map[i][j].y=j; map[i][j].nextX=-1; map[i][j].nextY=-1; } } BFS(); } return 0; }