hdu 2612 Find a way ( 双bfs )

版权声明:本文为博主原创文章,欢迎各位转载,但请带上本文地址。 https://blog.csdn.net/LD_1090815922/article/details/72448569

本题链接:点击打开链接

Find a way

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


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
 

Author
yifenfei
 

Source
 

Recommend
yifenfei   |   We have carefully selected several similar problems for you:   2717  1254  2102  1072  1253 
 
ps:以前做过的一个题,现在秒A,比较开心!另外这里我还是自己写了一个取两者较小值的函数,因为以前遇到调用函数库的函数时遇到过错误,所以后来比较简单的函数我都自己会再写一下,不用函数库的函数。

本题题意: Yifenfei和Merceki是好朋友,但很久没见面了。Yifenfei的家是在农村,但Merceki的家在城市的中心。所以yifenfei安排了Merceki在肯德基店见面。而当地有许多肯德基店,他们想选择一个让两个人花费总时间最短到达的肯德基店。
现在给你一个地图,yifenfei和Merceki可以在上,下,左,右邻路的点移动,每移动一个单位费时11分钟。
输入包含多个测试用例。
每个测试用例包括,前两个整数n,m。(2 < = n,m < = 200)。
接下来n行,每一行包含字符。
“Y”表达yifenfei初始位置。
“M”表达Merceki初始位置。
“#”表示禁止通行的道路。
“.”表示可以走的道路。
“@”表示KCF(肯德基店)。
解题思路:很容易想到这差不多是最短路的问题,所以用广搜来做。这个题应该来说还是广搜的基础题,这里只不过用了两次。为了保存他们到每个KFC的时间我用了两个数组来分别保存,假如mp[x][y]这一个点为KFC,那么a[x][y]表示Yifenfei到这个KFC用的时间,先不乘11,,最后输出再乘11是一样的。在bfs函数中用一个boll型的参数来区分记录是计算 yifenfei的用时还是Merceki的用时。先将他们到各个KFC的用时视为“无穷大”,然后再依次更新搜索到的到各个KFC的用时,最后找到他们到每个KFC时间总和最小的那一个值乘11再输出即可。队列相关知识我上一篇bfs博文中已提到,不再多说。


代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define inf 0x3f3f3f3f     //acm中“无穷大”的一般定义
using namespace std;
const int M=202;
char mp[M][M];            //地图
int a[M][M],b[M][M];
bool vis[M][M];           //标记数组
int n,m;
int ans;
struct node
{
    int x,y,step;
} s,ns;
int minn(int a,int b)    //取两数较小的一值的函数,调用min也可。
{
    return a<b ? a : b;
}
void init()              //初始化函数
{
    ans=inf;
    for(int i=0; i<n; i++)
        for(int j=0; j<m; j++)
        {
            a[i][j]=inf;
            b[i][j]=inf;
        }
}
bool ok(int x,int y)                //判断是否符合走(越界,是否已走过等)
{
    if(x>=0&&y>=0&&x<n&&y<m&&vis[x][y]&&mp[x][y]!='#')
        return true;
    return false;
}
void bfs(int x,int y,bool flag)       //flag=true,记录Merceki的时间,flag=alse,记录yifenfei 的时间
{
    int dir[4][2]= {{-1,0},{0,-1},{1,0},{0,1}}; //四个方向
    int nx,ny;
    queue<node>q;                      //将队列名设为q;
    s.x=x;
    s.y=y;
    s.step=0;
    vis[x][y]=false;
    q.push(s);                      //将第一个元素加入队列中
    while(!q.empty())               //队列中部位空就继续
    {
        s=q.front();                //再取出队列中的第一个元素赋值给结构体变量s
        q.pop();                    //删除第一个元素
        if(mp[s.x][s.y]=='@')
        {
            if(!flag)
                a[s.x][s.y]=s.step;
            if(flag)
                b[s.x][s.y]=s.step;
        }
        for(int i=0; i<4; i++)
        {
            nx=s.x+dir[i][0];
            ny=s.y+dir[i][1];
            if(ok(nx,ny))
            {
                vis[nx][ny]=false;         //已经游历就标记为false
                ns.x=nx;
                ns.y=ny;
                ns.step=s.step+1;
                q.push(ns);                //将下一位置元素压入队列中进行判断
            }
        }
    }
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        init();
        for(int i=0; i<n; i++)
            scanf("%s",mp[i]);
        for(int i=0; i<n; i++)
            for(int j=0; j<m; j++)
            {
                if(mp[i][j]=='Y')
                {
                    memset(vis,true,sizeof(vis));
                    bfs(i,j,false);
                }
                if(mp[i][j]=='M')
                {
                    memset(vis,true,sizeof(vis));  //记得再次初始化标记数组
                    bfs(i,j,true);
                }
            }
        for(int i=0; i<n; i++)
            for(int j=0; j<m; j++)
                if(mp[i][j]=='@')
                    ans=minn(ans,a[i][j]+b[i][j]);
        printf("%d\n",ans*11);
    }
    return 0;
}



猜你喜欢

转载自blog.csdn.net/LD_1090815922/article/details/72448569