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
题目大意:
模拟一个人走迷宫,遇到怪兽要和他决斗,决斗时间为那个格子的数字。输出(0,0)->(n-1,m-1)的最短路并输出路径。
感想:
题目并不是很难,本来可以一个小时之内过的,结果坑了我一下午。主要是我把存答案的数组开小了 。还有有两种存路径的方法 见下面的代码
代码1: 自己没用STL的代码 用结构存上一个点的坐标
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> const int INF=0x3f3f3f3f; #define maxn 105 using namespace std; int n,m,cxx; int sx,sy,ex,ey; int mp[maxn][maxn]; // 地图 int vis[maxn][maxn]; // 地图标记 int sta[maxn*maxn]; // 栈 int vissta[maxn*maxn]; // 标记栈是否访问 int dx[4]= {-1,1,0,0}; // 方向数组 int dy[4]= {0,0,-1,1}; char s[maxn],ans[1000005][40]; // 答案数组 注意一定不能吝啬内存 不然你会被坑的很惨 struct Tnode { int cnt; // 步数 int prex,prey; // 记录前一个点 } node[maxn][maxn]; bool bfs() { int i,x,y,nx,ny,tempx,tempy; int mi,k; int head=0,tail=-1; sta[++tail]=(sx-1)*m+sy; // 将行列对应值进栈 memset(vis,0,sizeof(vis)); memset(vissta,0,sizeof(vissta)); vis[sx][sy]=1; node[sx][sy].cnt=0; node[sx][sy].prex=-1; node[sx][sy].prey=-1; while(head<=tail) { mi=100000000; for(i=head; i<=tail; i++) // 模拟优先队列 找到栈中步数最小的 { tempy=sta[i]%m; if(tempy==0) tempy=m; tempx=(sta[i]-tempy)/m+1; if(node[tempx][tempy].cnt<mi&&!vissta[i]) { mi=node[tempx][tempy].cnt; k=i; } } y=sta[k]%m; // 计算栈对应的行列 if(y==0) y=m; x=(sta[k]-y)/m+1; vissta[k]=1; // 标记栈已经访问 while(vissta[head]) head++; // 移动栈头 if(x==ex&&y==ey) { return true; } for(i=0; i<4; i++) // bfs搜索进栈 { nx=x+dx[i]; ny=y+dy[i]; if(mp[nx][ny]<10&&!vis[nx][ny]) { sta[++tail]=(nx-1)*m+ny; vis[nx][ny]=1; node[nx][ny].prex=x; node[nx][ny].prey=y; node[nx][ny].cnt=node[x][y].cnt+mp[nx][ny]+1; } } } return false; } void solve(int t) // 找路径 往上推 存答案 { int i,j,temp; int su,sv,eu=ex,ev=ey; cxx=t+1; while(1) { su=node[eu][ev].prex; sv=node[eu][ev].prey; if(su==-1) break; if(mp[eu][ev]==0) { cxx--; sprintf(ans[cxx],"%ds:(%d,%d)->(%d,%d)",cxx,su-1,sv-1,eu-1,ev-1); } else { temp=mp[eu][ev]; while(temp--) { cxx--; sprintf(ans[cxx],"%ds:FIGHT AT (%d,%d)",cxx,eu-1,ev-1); } cxx--; sprintf(ans[cxx],"%ds:(%d,%d)->(%d,%d)",cxx,su-1,sv-1,eu-1,ev-1); } eu=su; ev=sv; } } int main() { int i,j; while(~scanf("%d%d",&n,&m)) { getchar(); memset(mp,0x3f,sizeof(mp)); // 初始化地图都不可以走 for(i=1; i<=n; i++) // 我将题图整体往斜下方移了一个单位 就能自动判断出界了 { scanf("%s",s); for(j=1; j<=m; j++) { if(s[j-1]=='.') mp[i][j]=0; else if(s[j-1]>='1'&&s[j-1]<='9') mp[i][j]=s[j-1]-'0'; } } sx=1; sy=1; ex=n; ey=m; if(bfs()) { printf("It takes %d seconds to reach the target position, let me show you the way.\n",node[ex][ey].cnt); solve(node[ex][ey].cnt); for(i=1;i<=node[ex][ey].cnt;i++) printf("%s\n",ans[i]); } else printf("God please help our poor hero.\n"); printf("FINISH\n"); } return 0; }
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <queue> #define maxn 105 using namespace std; const int INF=0x3f3f3f3f; int n,m,cxx; int mp[maxn][maxn]; // 地图 int vis[maxn][maxn]; // 标记数组 int dir[maxn][maxn]; // 记录方向数组 int dx[4]= {-1,1,0,0}; int dy[4]= {0,0,-1,1}; char s[maxn],ans[1000005][40]; struct Tnode { int cnt; int curx,cury; friend bool operator < (Tnode a,Tnode b) { return a.cnt>b.cnt; } } t1,now; priority_queue <Tnode> q; bool bfs() { int i,x,y,nx,ny; while(!q.empty()) q.pop(); t1.cnt=0; t1.curx=1; t1.cury=1; q.push(t1); memset(vis,0,sizeof(vis)); dir[1][1]=-1; vis[1][1]=1; while(!q.empty()) { now=q.top(); // 用优先队列可以保证每次出栈的都是步数最小的 y=now.cury; x=now.curx; q.pop(); if(x==n&&y==m) { cxx=now.cnt; return true; } for(i=0; i<4; i++) { nx=x+dx[i]; ny=y+dy[i]; if(mp[nx][ny]<INF&&!vis[nx][ny]) { vis[nx][ny]=1; dir[nx][ny]=i; t1.cnt=now.cnt+mp[nx][ny]+1; t1.curx=nx; t1.cury=ny; q.push(t1); } } } return false; } void solve() { int i,j,temp,t; int su,sv,eu=n,ev=m; t=cxx+1; while(1) { if(t<1) break; su=eu-dx[dir[eu][ev]]; // 通过方向找到上一个点的坐标 sv=ev-dy[dir[eu][ev]]; if(mp[eu][ev]>0) { temp=mp[eu][ev]; while(temp--) { t--; sprintf(ans[t],"%ds:FIGHT AT (%d,%d)",t,eu-1,ev-1); } } t--; sprintf(ans[t],"%ds:(%d,%d)->(%d,%d)",t,su-1,sv-1,eu-1,ev-1); eu=su; ev=sv; } } int main() { int i,j; while(~scanf("%d%d",&n,&m)) { getchar(); memset(mp,0x3f,sizeof(mp)); for(i=1; i<=n; i++) { scanf("%s",s); for(j=1; j<=m; j++) { if(s[j-1]=='.') mp[i][j]=0; else if(s[j-1]>='1'&&s[j-1]<='9') mp[i][j]=s[j-1]-'0'; } } if(bfs()) { printf("It takes %d seconds to reach the target position, let me show you the way.\n",cxx); solve(); for(i=1; i<=cxx; i++) printf("%s\n",ans[i]); } else printf("God please help our poor hero.\n"); printf("FINISH\n"); } return 0; }