[kuangbin带你飞]专题一 简单搜索—K - Find a way

K - Find a way


题目

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.

输入

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

输出

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.

样例输入

4 4
Y.#@
....
.#..
@..M
4 4
Y.#@
....
.#..
@#.M
5 5
Y..@.
.#...
.#...
@..M.
#...#

样例输出

66
88
66

题意
Yifenfei与Merceki约定一起去恰饭。

现给出地图,图中"Y"点与"M"点分别表示两个人家的位置,"@“点代表KFC(地图中不止存在一家KFC),”#“点代表墙,”."代表道路。

小Y和小M每走一格需要11min,输出两人会面所需的最短总时间(所用时间为两人用时相加)。

思路
这道题我足足用了将近2个小时才成功A掉,真的是印(wo)象(shi)深(f)刻(w)。

主要是一开始思路正确,代码实现过程出了问题,以至于一直卡壳。
被折磨了两个小时,差点自闭了,真的痛苦。
在这里插入图片描述

思路就是从不同的起点跑两次BFS,把这两个人到每个餐厅的步数和放在一个数组里:

int step[205][205];          //两个人到此点的步数之和  最后输出步数*11就可以了

BFS跑完之后,每个"@"在step数组中对应的位置就被赋好值了。
最后输出这些数中最小的minn*11就好了。

这里主要说一下这里的BFS内部开始搜索的过程:

//step数组一开始会全部初始化为0
while(!q.empty())
    {
        node tmp = q.front();
        if(a[tmp.x][tmp.y]=='@')               //当这个点是KFC时
            step[tmp.x][tmp.y] += tmp.hour;    //对应位置的step加上现在这个点的步数
        q.pop(); 
        for(int i=0; i<4; i++)
        {
            int xx = tmp.x+dx[i];
            int yy = tmp.y+dy[i];
            if(a[xx][yy]!='#'&&!vis[xx][yy]&&xx>=0&&xx<n&&yy>=0&&yy<m)
            {
                vis[xx][yy] = true;
                q.push(node(xx,yy,tmp.hour+1));
            }
        }
    }

这是代码的核心,如果不是很懂的话可以结合完整代码,自己推导一下具体过程。

还有一个关键的点,不少人可能是因为这个点而过不去。

YM.
#..
@#@

这种情况下左下角的KFC我们无法到达,step[2][0]=0。

如果我们这样写:

  for(int i =0; i<n; i++)
            for(int j=0; j<m; j++)
                if(a[i][j]=='@')         
                {
                    minn = min(minn,step[i][j]);
                }

那么输出就会是0,这样的话就W掉了。

所以这个地方我们这样写:

for(int i =0; i<n; i++)
            for(int j=0; j<m; j++)
                if(step[i][j])      //step[i][j]!=0时表示该点是一个能够到达的餐厅     
                {
                    minn = min(minn,step[i][j]);
                }

最后,「伊丽莎白」!
在这里插入图片描述
代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<vector>
using namespace std;
struct node
{
    int x,y,hour;
    node() {}
    node(int xx,int yy,int zz):x(xx),y(yy),hour(zz) {}
};
bool vis[205][205];
int step[205][205];          //两个人到此点的步数之和  时间的话最后输出步数*11就可以了
char a[205][205];
int dx[4]= {1,-1,0,0};
int dy[4]= {0,0,1,-1};
int n,m;
void bfs(int x1,int y1)
{
    queue<node>q;
    memset(vis,false,sizeof(vis));             //重置标记数组
    q.push(node(x1,y1,0));
    vis[x1][y1] = true;
    while(!q.empty())
    {
        node tmp = q.front();
        if(a[tmp.x][tmp.y]=='@')               //当这个点是KFC时
            step[tmp.x][tmp.y] += tmp.hour;    //对应位置的step加上现在这个点的步数
        q.pop(); 
        for(int i=0; i<4; i++)
        {
            int xx = tmp.x+dx[i];
            int yy = tmp.y+dy[i];
            if(a[xx][yy]!='#'&&!vis[xx][yy]&&xx>=0&&xx<n&&yy>=0&&yy<m)
            {
                vis[xx][yy] = true;
                q.push(node(xx,yy,tmp.hour+1));
            }
        }
    }
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        memset(step,0,sizeof(step));   //重置step数组
        char s[205];                   //用于输入
        int x1,x2,y1,y2;
        int minn = 0x3f3f3f3f;         //minn取大一些
        for(int i=0; i<n; i++)
        {
            cin>>s;
            for(int j=0; j<m; j++)
            {
                a[i][j] = s[j];
                if(a[i][j]=='Y')       //记录小Y坐标
                {
                    x1 = i;
                    y1 = j;
                }
                if(a[i][j]=='M')       //记录小M坐标
                {
                    x2 = i;
                    y2 = j;
                }
            }
        }
        bfs(x1,y1);                    //起点为小Y
        bfs(x2,y2);                    //起点为小M
        //两次BFS之后,step数组中@对应位置已存入两人到达此处的步数之和。
        for(int i =0; i<n; i++)
            for(int j=0; j<m; j++)
                if(step[i][j])         
                {
                    minn = min(minn,step[i][j]);
                }
        cout<<minn*11<<endl;
    }
}



扛了2小时的一袋米,裂开了。

溜了溜了~
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值