2018年东北农业大学春季校赛H题wyh的吃鸡

题目描述 

最近吃鸡游戏非常火,你们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的地图,每个字符都是上面的一种,并且保证只有一个起点,只有一块安全区域。

输出描述:

对于每组测试数据,先输出能否到达,能的话输出YES,然后换行输出最短时间,如果不能的话直接输出NO
示例1

输入

3
2 3
.X
S.
2 3
.X
SC
2 4
.X
S.

输出

NO
YES
3
YES
4

思路:X可能不止一个可能是一个连通块,可以用最短路来写。

代码:

#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
#define ll long long
const int N=1000+10;
char s[N][N];
int dis[N][N][2];
int vis[N][N][2];
struct node
{
    int x,y,z;
};
int m,n,z;
int x[N*N],y[N*N];
bool check(int a,int b)
{
    if(a<0||a>=n||b<0||b>=n||s[a][b]=='O')return true;
    return false;
}
int dir[4][2]={1,0,-1,0,0,1,0,-1};
int sx,sy;
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        scanf("%d%d",&n,&m);
        memset(vis,0,sizeof(vis));
        for(int i=0;i<n;i++)
            scanf("%s",s[i]);
        z=0;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(s[i][j]=='S')sx=i,sy=j;
                if(s[i][j]=='X')x[z]=i,y[z++]=j;
                dis[i][j][0]=dis[i][j][1]=inf;
            }
        }
       queue<node>Q;
    node p,q;
    p.x=sx;
    p.y=sy;
    p.z=0;
    dis[sx][sy][0]=0;
    vis[sx][sy][0]=1;
    Q.push(p);
    while(!Q.empty())
    {
        q=Q.front();
        Q.pop();
        vis[q.x][q.y][q.z]=0;
        for(int i=0;i<4;i++)
        {
            p.x=q.x+dir[i][0];
            p.y=q.y+dir[i][1];
            p.z=q.z;
            if(check(p.x,p.y))continue;
            if(s[p.x][p.y]=='C')p.z=1;
            int c;
            if(q.z==0)c=2;
            else c=1;
            if(dis[q.x][q.y][q.z]+c<dis[p.x][p.y][p.z])
            {
                dis[p.x][p.y][p.z]=dis[q.x][q.y][q.z]+c;
                if(vis[p.x][p.y][p.z]==0)
                {
                    vis[p.x][p.y][p.z]=1;
                    Q.push(p);
                }
            }
        }

    }
    int ans=inf;
    for(int i=0;i<z;i++)
    {
        ans=min(ans,dis[x[i]][y[i]][0]);
        ans=min(ans,dis[x[i]][y[i]][1]);
    }
    if(ans<=m){
        printf("YES\n");
      printf("%d\n", ans);
    }
    else printf("NO\n");
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值