1. 程式人生 > >2018年東北農業大學春季校賽H題wyh的吃雞

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;
}