HDU 2612 Find a way(BFS)

Find a way

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 18666    Accepted Submission(s): 6034


Problem Description
Pass a year learning in Hangzhou, yifenfei arrival hometown Ningbo at finally. Leave Ningbo one year, yifenfei have many people to meet. Especially a good friend Merceki.
Yifenfei’s home is at the countryside, but Merceki’s home is in the center of city. So yifenfei made arrangements with Merceki to meet at a KFC. There are many KFC in Ningbo, they want to choose one that let the total time to it be most smallest. 
Now give you a Ningbo map, Both yifenfei and Merceki can move up, down ,left, right to the adjacent road by cost 11 minutes.
 

Input
The input contains multiple test cases.
Each test case include, first two integers n, m. (2<=n,m<=200). 
Next n lines, each line included m character.
‘Y’ express yifenfei initial position.
‘M’    express Merceki initial position.
‘#’ forbid road;
‘.’ Road.
‘@’ KCF
 

Output
For each test case output the minimum total time that both yifenfei and Merceki to arrival one of KFC.You may sure there is always have a KFC that can let them meet.
 

Sample Input
  
  
4 4 Y.#@ .... .#.. @..M 4 4 Y.#@ .... .#.. @#.M 5 5 Y..@. .#... .#... @..M. #...#
 

Sample Output
  
  
66 88 66

思路:

刚看到这题感觉还行,思路一下出来了。

两人走过的路分别标记,进行广搜,每个KFC加上2人在该KFC最小步数即可。

WA了一发后,眉头一皱,发现事情并不简单。


但是找不到哪错了啊菜哭,看了讨论区才知道原来存在两人都到不了的情况ORZ。


所以最后思路是,两人的走过的路分别标记,进行广搜,每个KFC加上2人在该KFC最小步数,用3维数组存各点答案,多出来的一维记录该点被到达过几次(至多2次),最后遍历地图找到KFC上被到达2次点中最小值即可


代码:

#include<stdio.h>  
#include<string.h>  
#include<stdlib.h>  
#include<math.h>  
#include<algorithm>  
#include<queue>  
using namespace std;  
#define mod 1000000007  
#define ll long long  
#define INF 0x3f3f3f3f  
#define mem(a,b) memset(a,b,sizeof(a))  
  
char start[205][205];   //存地图  
//book标记该点是否被到达,ans存答案,mov是移动方向  
int book1[205][205],book2[205][205],ans[205][205][2],mov[4][2]={0,1,1,0,0,-1,-1,0};  
  
//x,y存坐标,step存步数,who存Y还是M,Y为1,M为2,和book对应好记一点  
struct node  
{  
    int x,y,step,who;  
}st,ne;  
  
int main(){  
    int row,col,i,j;  
    while(~scanf("%d%d",&row,&col)){  
        mem(book1,0);  
        mem(book2,0);  
        mem(start,0);  
        mem(ans,0);  
        queue<node> q;  
        for(i=1;i<=row;i++)scanf("%s",start[i]+1);  
          
        //起点入队  
        for(i=1;i<=row;i++){  
            for(j=1;j<=col;j++){  
                if(start[i][j]=='Y'){  
                    st.step=0;  
                    st.x=i;  
                    st.y=j;  
                    st.who=1;  
                    book1[i][j]=1;  
                    q.push(st);  
                }  
                if(start[i][j]=='M'){  
                    st.step=0;  
                    st.x=i;  
                    st.y=j;  
                    st.who=2;  
                    book2[i][j]=1;  
                    q.push(st);  
                }  
            }  
        }  
  
        while(!q.empty()){  
            st=q.front();  
              
//判断出队比较省代码长度,应该也不会差这一点时间  
            if(start[st.x][st.y]=='@'){  
                if(ans[st.x][st.y][0])ans[st.x][st.y][1]=1; //如果该点已经被到达过第三维标记1  
                ans[st.x][st.y][0]+=st.step;  
            }  
            q.pop();  
            ne.step=st.step+1;  
            ne.who=st.who;  
            for(i=0;i<4;i++){  
                ne.x=st.x+mov[i][0];  
                ne.y=st.y+mov[i][1];  
  
                if(ne.x<1||ne.x>row||ne.y<1||ne.y>col)continue; //越界,没用这行应该也没事(每次输入前都清空地图了),不过养成习惯应该好点  
  
                //两者分别判断  
                if(ne.who==1&&book1[ne.x][ne.y]==0&&start[ne.x][ne.y]!='#'){  
                    book1[ne.x][ne.y]=1;  
                    q.push(ne);  
                }  
  
                if(ne.who==2&&book2[ne.x][ne.y]==0&&start[ne.x][ne.y]!='#'){  
                    book2[ne.x][ne.y]=1;  
                    q.push(ne);  
                }  
            }  
        }  
  
        //遍历地图找到KFC上被到达2次点中最小值  
        int minn=INF;  
        for(i=1;i<=row;i++)  
            for(j=1;j<=col;j++)  
                if(start[i][j]=='@'&&ans[i][j][1]==1&&ans[i][j][0]<minn)  
                    minn=ans[i][j][0];  
        printf("%d\n",minn*11);  
    }  
    return 0;  
}  


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值