N - Find a way HDU - 2612 (18,9,15)

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见面,但是他们家附近有很多KFC,这道题就是找一个KFC使两个人到这个KFC的时间和是最小的,就是找一条最短路

易错点:起初我是每次都从头开始搜,求Y到当前我所指定KFC的时间,在求M到我当前所指定的KFC的时间,然后这两个时间相加与mmin相比,然后我在搜索他们两人到另一个KFC的时间和,直到把两个人到所有的KFC的时间和都算过了,比较出最小值,最后输出。但是这样的方法会时间超限,假如KFC比较多的话。

解题思路:

为了解决超时问题,另外开辟了一个数组,steps[203][203][2],  steps[x][y][0]用来存放Y到每个所给出的KFC的时间,step[x][y][1]用来存放M到每个所给出的KFC的时间。

分别以Y为起点,M为起点进行广搜,在一次广搜中就将他们到每个KFC的时间都求出,然后如果cmap[i][j]=='@'

我们就求 (steps[i][j][0]+steps[i][j][1])  于  mmin的最小值

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
#define INF 0x3f3f3f3f  //定义INF为正无穷
using namespace std;
struct pos  
{
    int x;  //横坐标
    int y;  //纵坐标
    int step;  //走到当前位置的步数
};
pos s1,s2,s;  //s1位Y的位置,s2位M的位置,s是临时变量
char cmap[203][203];  //203*203的矩阵
int vis[203][203];          //用来标记一个地方走没有走过的数组
int n,m,mmin,flag; //行,列,最小值,flag
int dir[4][2]={{-1,0},{0,1},{1,0},{0,-1}};  //广搜的四个方向
int steps[203][203][2];  //用来存放两个人到某个KFC的一个数组。
void bfs(int x1,int y1)  //参数是起点坐标
{
    int i;
    memset(vis,0,sizeof(vis));   //每次调用函数时都要,将vis初始化为0,恢复为原来的状态
    pos cur,next;    //cur当前位置,next下一位置
    s.x=x1;s.y=y1;s.step=0;   //起始位置的横纵坐标,步数为0
    vis[s.x][s.y]=1;                 //将起始位置标记为已经走过了 
    queue<pos>Q;              //定义一个名为Q的队列,存放的是结构体变量
    Q.push(s);                    //起点进队
    while(!Q.empty())     //队列不空
    {
        cur=Q.front();   //当前位置为队首元素的位置
        Q.pop();           
        next.step=cur.step+1;   //下一位置的步数等于当前位置的步数加1
        for(i=0;i<4;i++)  //四个方向走
        {
            next.x=cur.x+dir[i][0];
            next.y=cur.y+dir[i][1];
            if(next.x>0&&next.x<=n&&next.y>0&&next.y<=m&&cmap[next.x][next.y]!='#'&&vis[next.x][next.y]==0)//这个位置不越界,能走,而且还没有走过
            {
                vis[next.x][next.y] = 1;  //将这个位置标记为1,代表走过
                if(cmap[next.x][next.y] == '@')  //如果当前位置是KFC,我们就把当前的步数赋给steps数组对应的位置
                    steps[next.x][next.y][flag] = next.step;
                Q.push(next);  //进队
            }
        }
    }
}
int main()
{
    int i,j;
    while(~scanf("%d%d",&n,&m))  //行数,列数
    {
        mmin=INF;  //最小值初始化为正无穷
        for(i=0;i<=n;i++)
            for(j=0;j<=m;j++)
            {
                steps[i][j][0]=INF;  //将steps数组初始化为INF
                steps[i][j][1]=INF;
            }
        for(i=1;i<=n;i++)
            for(j=1;j<=m;j++)
            {
                scanf(" %c",&cmap[i][j]);
                if(cmap[i][j]=='Y')   //记录两个起点的位置
                {
                    s1.x=i; s1.y=j;
                }
                else if(cmap[i][j]=='M')
                {
                    s2.x=i; s2.y=j;
                }
            }
       flag=0;  
       bfs(s1.x,s1.y);  //用来求Y到所有KFC的时间
       flag=1;
       bfs(s2.x,s2.y);  //用来求M到所有KFC的时间
       for(i=1;i<=n;i++)
        for(j=1;j<=m;j++)
        {
            if(cmap[i][j]=='@')  //如果这个位置为KFC,我们就取出对应位置的steps中的值
            {
                if(steps[i][j][0]+steps[i][j][1]<mmin)  //如果两者的时间相加比最小时间小
                    mmin=steps[i][j][0]+steps[i][j][1];   //那么我就更新最小时间
            }
        }
        printf("%d\n",mmin*11);   //最后乘上11输出答案。
    }
    return 0;
} 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值