2018年東北農業大學春季校賽H題wyh的吃雞
阿新 • • 發佈:2019-01-26
題目描述
最近吃雞遊戲非常火,你們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; }