2018年东北农业大学春季校赛 H-why的吃鸡 (bfs)

链接: https://www.nowcoder.com/acm/contest/93/H
来源:牛客网

题目描述

最近吃鸡游戏非常火,你们wyh学长也在玩这款游戏,这款游戏有一个非常重要的过程,就是要跑到安全区内,否则就会中毒持续消耗血量,我们这个问题简化如下

假设地图为n*n的一个图,图中有且仅有一块X的联通快代表安全区域,有一个起点S代表缩圈的时候的起点,图中C代表的是车(保证车的数量小于等于100),标记为.的代表空地,可以任意通过,O代表障碍物不能通过。每次没有车的时候2s可以走一个格(只能走自己的上下左右4个方向),有车的话时间为1s走一个格

现在告诉你最多能坚持的时间为t秒,问你在t秒内(含t秒)能否从s点到达安全区域,能的话输出YES,并且输出最短时间,不能的话输出NO

输入描述:

输入第一行一个整数T(1<=T<=10)
接下来有T组测试数据,每组测试数据输入2个数n和k(1<=n<=100,1<=k<=10^9)
接下来n行,每行n个字符,代表对应的n*n的地图,每个字符都是上面的一种,并且保证只有一个起点,只有一块安全区域。

题解:
有两种情况,1.从起点到车,开车到终点。2.从起点走到终点。
从起点出发遍历整张图,遇到车标记一下距离,
从终点遍历整张图,遇到车标记一下,这里要注意
终点是一个联通块,因此把联通块中的点全部加入队列中然后bfs

代码:

#include<bits/stdc++.h>
using namespace std;
char t[1005][1005];
int x1,y2;
int d[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
bool is[102][102];
int d1[105][105],d2[105][105],n,k;
struct node
{
    int x,y,step;
};
queue<node>P;
void bfs(int k)
{
    while(!P.empty())
    {
        node e=P.front();P.pop();
        if(t[e.x][e.y]=='C')
        {
            if(k==2)d1[e.x][e.y]=e.step;
            else d2[e.x][e.y]=e.step*2;//走路时间加倍
        }
        for(int i=0;i<4;i++)
        {
            int x=e.x+d[i][0],y=e.y+d[i][1];
            if(x>=0&&x<n&&y>=0&&y<n&&!is[x][y]&&t[x][y]!='O')
            {
                node r;r.x=x,r.y=y,r.step=e.step+1;
                P.push(r);
                is[x][y]=1;
            }
        }
    }
}
int bfs1()
{
    memset(is,0,sizeof(is));
    node h;h.x=x1,h.y=y2,h.step=0;
    P.push(h);
    while(!P.empty())
    {
        node e=P.front();P.pop();
        if(t[e.x][e.y]=='X')
        {
            return e.step*2;
        }
        for(int i=0;i<4;i++)
        {
            int x=e.x+d[i][0],y=e.y+d[i][1];
            if(x>=0&&x<n&&y>=0&&y<n&&!is[x][y]&&t[x][y]!='O')
            {
                node r;r.x=x,r.y=y,r.step=e.step+1;
                P.push(r);
                is[x][y]=1;
            }
        }
    }
    return 1e9;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        for(int i=0;i<105;i++)
            for(int j=0;j<105;j++)
            d1[i][j]=d2[i][j]=1e9;
        scanf("%d%d",&n,&k);
        for(int i=0; i<n; i++)
            scanf("%s",&t[i]);
        for(int i=0; i<n; i++)
            for(int j=0; j<n; j++)
                if(t[i][j]=='S')x1=i,y2=j;
        node e;e.x=x1,e.y=y2;e.step=0;
        P.push(e);
        memset(is,0,sizeof(is));
        is[x1][y2]=1;
        bfs(1);
        memset(is,0,sizeof(is));
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
        {
            if(t[i][j]=='X')
            {
                node e;e.x=i,e.y=j,e.step=0;
                P.push(e);
                is[i][j]=1;
            }
        }
        bfs(2);
        int ans1=bfs1();
        while(!P.empty())P.pop();
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
        {
            if(t[i][j]=='C')//注意并不是每一辆车都能走得到,因此要初始化d位无穷大
            {
                ans1=min(ans1,d1[i][j]+d2[i][j]);
            }
        }
        if(ans1<=k) printf("YES\n%d\n",ans1);
        else printf("NO\n");
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值