聂老师的考验(反向bfs)

题目链接: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\n");
80         else printf("%d\n",ans);
81     }
82 }

 

 

转载于:https://www.cnblogs.com/Dillonh/p/8608510.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值