题目链接:http://113.240.233.2:8081/JudgeOnline/problem.php?id=1121
这个题看起来要多次使用bfs,其实只要换个思维就会发现这就是一个简单的bfs裸题。不要从P开始bfs,要从W开始bfs,然后到达P的话就将W与P间的距离加上,如果达到F的话,先存起来,最后sort一下,最远的加一次,其他的加两次(因为每点燃一次火炬台就会失去小火炬又得重新回去,所以要加两次;但是最远的那个根据距离可以判断它是最后一个火炬台,把它点燃之后就不需要再回W取小火炬了,因此只需加一次)。代码实现如下:
1 #include <cstdio> 2 #include <queue> 3 #include <algorithm> 4 #include <cstring> 5 using namespace std; 6 7 int n,m,sx,sy,ans,t,k; 8 char mp[105][105]; 9 int vis[105][105],cost[10007]; 10 11 struct node{ 12 int x,y,step; 13 }nw,nxt; 14 15 int dx[4]={1,-1,0,0},dy[4]={0,0,1,-1}; 16 17 void bfs(int x,int y){ 18 queue<node> q; 19 nw.x=x,nw.y=y,nw.step=0; 20 vis[nw.y][nw.x]=1; 21 q.push(nw); 22 while(!q.empty()){ 23 nw=q.front();q.pop(); 24 if(mp[nw.y][nw.x]=='P'){ 25 t=nw.step; 26 mp[nw.y][nw.x]='.'; 27 } 28 if(mp[nw.y][nw.x]=='F'){ 29 cost[k++]=nw.step; 30 mp[nw.y][nw.x]='.'; 31 } 32 for(int i=0;i<4;i++){ 33 nxt.x=nw.x+dx[i],nxt.y=nw.y+dy[i]; 34 if(nxt.x>=0 && nxt.x<m && nxt.y>=0 && nxt.y<n && mp[nxt.y][nxt.x]!='#' && vis[nxt.y][nxt.x]==0){ 35 nxt.step=nw.step+1; 36 vis[nxt.y][nxt.x]=1; 37 q.push(nxt); 38 } 39 } 40 } 41 } 42 43 int main(){ 44 while(~scanf("%d%d",&n,&m)){ 45 if(n==0 && m==0) break; 46 for(int i=0;i<n;i++){ 47 scanf("%s",mp[i]); 48 } 49 memset(vis,0,sizeof(vis)); 50 memset(cost,0,sizeof(cost)); 51 ans=0,t=0,k=0; 52 for(int i=0;i<n;i++){ 53 for(int j=0;j<m;j++){ 54 if(mp[i][j]=='W'){ 55 sx=j,sy=i; 56 break; 57 } 58 } 59 } 60 bfs(sx,sy); 61 sort(cost,cost+k); 62 for(int i=0;i<k;i++){ 63 if(i!=k-1){ 64 ans+=cost[i]*2; 65 } 66 else{ 67 ans+=cost[i]; 68 } 69 } 70 ans+=t; 71 int flag=0; 72 for(int i=0;i<n;i++){ 73 for(int j=0;j<m;j++){ 74 if(mp[i][j]=='F' || mp[i][j]=='P'){ 75 flag=1; 76 } 77 } 78 } 79 if(flag) printf("No "); 80 else printf("%d ",ans); 81 } 82 }