HDU 5040 Instrusive
2014 ACM/ICPC Asia RegionalBeijing Online I题
题意:给定一个N*N的矩阵,matt从M点出发要到达T点,矩阵中某些格子会有相机,首先相机有一个初始方向,之后每1秒钟顺时钟转动一次方向,如果matt走进一个正在被相机观察到的点或者matt从一个正在在相机观察的点离开的话,那么matt只能使用工具躲进里面,这样的话需要3s中移动一次,matt可以(使用工具)在某些格子停留不动,问matt从M点到达t点的最短时间是多少?
首先,如果直接按题意来扩展状态的话,因为每一步扩展状态的时间不同,那么必须使用优先队列加速搜索并找到最短的时间,每次只有几种情况:1、待在原地不动,时间+1。2、正在的点或要去的点正在被相机观察,则时间+3。3、不在相机视野内,则时间+1。
因此我们只需要处理好判断一个点是否在相机范围内就行了,考虑到相机的变化,那么对于每一个格子有4种状态,标记去重就行了。
这题和以前做过的hdu1180差不多是一样的…..
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
#define LL long long
#define INF 0x3f3f3f3f
#define N 510
using namespace std;
struct po{
int x, y, time;
po(int a, int b, int c):x(a), y(b), time(c){}
bool operator > (const po &a) const {return time > a.time;}
};
int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
char mat[N][N];
int vis[N][N][5], sx, sy, n;
inline int check(int x, int y)
{
return x >= 0 && x < n && y >=0 && y < n && mat[x][y] != '#';
}
inline int in_camera(int x, int y, int t)
{
if (mat[x][y] == 'N' || mat[x][y] == 'E' || mat[x][y] == 'S' || mat[x][y] == 'W') return 1;
for (int i = 0; i < 4; i++){
int nx = x+dx[i], ny = y+dy[i];
if (check(nx, ny)){
if (mat[nx][ny] == 'S' && t%4 == i%4) return 1;
if (mat[nx][ny] == 'W' && t%4 == (i+3)%4) return 1;
if (mat[nx][ny] == 'N' && t%4 == (i+2)%4) return 1;
if (mat[nx][ny] == 'E' && t%4 == (i+1)%4) return 1;
}
}
return 0;
}
int bfs()
{
priority_queue<po, vector<po>, greater<po> > q;
memset(vis, 0, sizeof(vis));
q.push(po(sx, sy, 0));
vis[sx][sy][0] = 1;
while (!q.empty()){
po t = q.top(); q.pop();
if (mat[t.x][t.y] == 'T') return t.time;
if (!vis[t.x][t.y][(t.time+1)%4]) q.push(po(t.x, t.y, t.time+1));
for (int i = 0; i < 4; i++){
int nx = t.x+dx[i], ny = t.y+dy[i];
if (check(nx, ny)){
if (in_camera(t.x, t.y, t.time) || in_camera(nx, ny, t.time)){
if (!vis[nx][ny][(t.time+3)%4]) {
q.push(po(nx, ny, t.time+3));
vis[nx][ny][(t.time+3)%4] = 1;
}
}
else {
if (!vis[nx][ny][(t.time+1)%4]){
q.push(po(nx, ny, t.time+1));
vis[nx][ny][(t.time+1)%4] = 1;
}
}
}
}
}
return -1;
}
int main()
{
int t, k = 0;
scanf("%d", &t);
while (t--){
scanf("%d", &n);
int flag = 1;
for (int i = 0; i < n; i++){
scanf("%s", mat[i]);
for (int j = 0; j < n && flag; j++)
if (mat[i][j] == 'M') {sx = i, sy = j; flag = 0; break;}
}
printf("Case #%d: %d\n", ++k, bfs());
}
return 0;
}