Description
一个每块地板标记着0~9某个数字的迷宫,其中标记1的地板不可以走,标记2~9的地板可以不花时间地跳到任意相同数字的位置,也可以和标记0的地板一样向前后左右任意方向花1个单位时间移动1的距离。给出起点和终点,求起点到终点的最短时间。
Input
每组数据第一行一个n,表示尺寸,2 <= n <= 100。
接下来n行每行n个0~9的字符,或S表示起点,E表示终点,S和E的运动规则与0相同。整个地图只有一个S和一个E。
Output
每组数据输出一个数,占一行,表示起点到终点可以花费的最短时间。
如果无法到达重点,输出"Oh No!"
Sample Input
5
0S100
00131
00300
00000
003E0
3
S12
010
10E
Sample Output
4
Oh No!
分析:这题表面上是BFS的题,实质上是最短路的题,用到了spfa的思想。

#include <stdio.h> #include <string.h> #include <queue> using namespace std; #define N 101 int dx[4]={0,0,1,-1}; int dy[4]={1,-1,0,0}; struct node { int x,y; }; int n; int t[N][N],inq[N][N]; char map[N][N]; int px[10][N*N],py[10][N*N]; int cnt[10]; int sx,sy,ex,ey; void spfa() { queue<node> q; int x,y,nx,ny; int ans; node cur,next; bool f[10]; bool success=false; memset(f,0,sizeof(f)); memset(t,-1,sizeof(t)); memset(inq,0,sizeof(inq)); cur.x=sx; cur.y=sy; t[sx][sy]=0; q.push(cur); inq[sx][sy]=1; while(!q.empty() && !success) { cur=q.front(),q.pop(); x=cur.x; y=cur.y; inq[x][y]=0; if(x==ex && y==ey) { success=true; ans=t[x][y]; } for(int i=0;!success && i<4;i++) { nx=x+dx[i]; ny=y+dy[i]; if(nx<0 || ny<0 || nx>=n || ny>=n || map[nx][ny]=='1') continue; next.x=nx; next.y=ny; if(map[nx][ny]>='2' && map[nx][ny]<='9' && !f[map[nx][ny]-'0']) { int k=map[nx][ny]-'0'; f[k]=true; for(int i=0;i<cnt[k];i++) { nx=px[k][i]; ny=py[k][i]; next.x=px[k][i]; next.y=py[k][i]; t[nx][ny]=t[x][y]+1; inq[nx][ny]=1; q.push(next); } } else if(t[nx][ny]==-1 || t[nx][ny]>t[x][y]+1) { t[nx][ny]=t[x][y]+1; if(!inq[nx][ny]) { inq[nx][ny]=1; q.push(next); } } } } if(success) printf("%d\n",ans); else puts("Oh No!"); } int main() { int i,j,k; while(~scanf("%d",&n)) { memset(cnt,0,sizeof(cnt)); for(i=0;i<n;i++) { scanf("%s",map[i]); for(j=0;j<n;j++) { if(map[i][j]=='S') sx=i,sy=j; if(map[i][j]=='E') ex=i,ey=j; if(map[i][j]>='2' && map[i][j]<='9') { k=map[i][j]-'0'; px[k][cnt[k]]=i; py[k][cnt[k]++]=j; } } } spfa(); } return 0; }