1147: 翼神的跑毒之旅
Time Limit:4000/2000 MS (Java/Others) Memory Limit:163840/131072 KB (Java/Others)
Total Submissions:43 Accepted:7
[Submit][Status][Discuss]
Description
翼神沉迷吃鸡,但他的技术和人品只能让他不断跑毒。
给定n∗n的格点表示游戏地图,安全区则由一片标记为’X’的联通区域构成,翼神从标记为’S’的点出发,只有在k秒内跑进安全区就可以活下去。
一般情况下,翼神需要花费2秒时间只向左、向右、向上或向下走过1个格点,但地图上标记为’C’的点有车(保证车的数量≤100),翼神驾车时只需花费1秒钟就能通过1个格点。
当然问题并没有简单,地图上只有标记为’.’的点可以通过(当然标记为’X’,’S’与标记为’C’的区域也同样可以通过),而标记为’O’的点则是翼神无法穿过的悬崖和陡坡。
请问翼神能否活下去?如果能活下去,翼神抵达安全区的最快时间是多少?
Input有t组样例t≤10,每组样例包含两个整数n,k,1≤n≤100,k≤109
接下来包含一张n∗n的地图。
Output
首先判断翼神是否能够存活,如果不能,输出“NO”,如果可以存活,输出”YES”并输出翼神抵达安全区的最快时间。
Sample Input
3
2 3
.X
S.
2 3
.X
SC
2 4
.X
S.
Sample Output
NO
YES
3
YES
4
题解:由于图的规模是100*100,所以无法进行dfs,但是我们可以采用bfs(由于是无权图),比dfs快的多。先从起点S开始,进行bfs对经过的C位置进行记录,同时使用shortes[maxn][maxn]数组,记录任意点到S的最短路,这样会得到完全步行的最短时间,之后在对每一处记录的车的位置进行bfs,对所有答案取最小值,这样就是最优解,与K进行比较即可。
代码:
#include<iostream>
#include<fstream>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<stdio.h>
#include<utility>
#include<algorithm>
#include<map>
#include<stack>
#include<set>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn = 105;
const int mod = 1e9+7;
const int INF = 1<<30;
const ll llINF = 1e18+999;
int k, n, T, isvisited[maxn][maxn], shortest[maxn][maxn], ans;
struct node
{
int xx, yy;
node(int a, int b)
{
xx = a;
yy = b;
}
};
queue<node> car;
char arr[maxn][maxn];
void bfs(int x, int y, int speed)
{
memset(isvisited, 0, sizeof(isvisited));
isvisited[x][y] = 1;
queue<node> q;
q.push(node(x, y));
while(!q.empty())
{
node node1 = q.front( );
q.pop( );
x = node1.xx;
y = node1.yy;
if(arr[x][y] == 'X')
{
ans = min(ans, shortest[x][y]);
return;
}
if(arr[x][y] == 'C' && speed==2)
car.push(node(x, y));
if(x-1>-1 && arr[x-1][y]!='O' && !isvisited[x-1][y])
{
isvisited[x-1][y] = 1;
shortest[x-1][y] = shortest[x][y]+speed;
q.push(node(x-1, y));
}
if(x+1<n && arr[x+1][y]!='O' && !isvisited[x+1][y])
{
isvisited[x+1][y] = 1;
shortest[x+1][y] = shortest[x][y] + speed;
q.push(node(x+1, y));
}
if(y-1>-1 && arr[x][y-1]!='O' && !isvisited[x][y-1])
{
isvisited[x][y-1] = 1;
shortest[x][y-1] = shortest[x][y] + speed;
q.push(node(x, y-1));
}
if(y+1<n && arr[x][y+1]!='O' && !isvisited[x][y+1])
{
isvisited[x][y+1] = 1;
shortest[x][y+1] = shortest[x][y] + speed;
q.push(node(x, y+1));
}
}
}
int main( )
{
//freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
scanf("%d", &T);
while(T--)
{
memset(shortest, 0, sizeof(shortest));
while(!car.empty())
car.pop();
ans = INF;
scanf("%d%d", &n, &k);
for(int i=0; i<n; i++)
scanf("%s", arr[i]);
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
if(arr[i][j] == 'S')
bfs(i, j, 2);
while(!car.empty())
{
node node1 = car.front( );
car.pop();
bfs(node1.xx, node1.yy, 1);
}
if(ans > k)
cout<<"NO"<<endl;
else
cout<<"YES"<<endl<<ans<<endl;
}
return 0;
}