传送门:HDU 5040
题意:给定一张图,Matt要从M移动到T取偷东西,N,W,S,E表示这些位置有监控器,字母表示这些监控器的初始方向,并且每一秒顺时针旋转90度。现在Matt每移动一格需要花一秒,但是如果当前他所在的位置或者他要去的位置被监控器监视,那么如果他要移动,就必须躲在箱子里移动,时间需要花费3秒。或者也可以选择不移动,躲在箱子里1秒,问Matt最少花费多少时间移动到T。
思路:很明显的bfs,就是题意很坑,一开始还以为摄像头第一秒照初始方向,最后才知道是从0秒开始计数的。。
我是预处理出来每个地方在第几秒会被摄像头照到(%4的循环),并状压存储,然后就搜就行了,注意标记点的时候要进行3维标记,即记录%4的每一种情况是否到过这个点。
代码:
#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
typedef pair<int,int> P;
const int MAXN = 510;
int n, sr, sc, er, ec;
char mp[MAXN][MAXN];
int face[MAXN][MAXN];
void init()
{
memset(face, 0, sizeof(face));
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= n; j++)
{
if(mp[i][j] == 'N')
{
face[i][j] = 15;
face[i - 1][j] |= (1 << 0);
face[i][j + 1] |= (1 << 1);
face[i + 1][j] |= (1 << 2);
face[i][j - 1] |= (1 << 3);
}
if(mp[i][j] == 'E')
{
face[i][j] = 15;
face[i][j + 1] |= (1 << 0);
face[i + 1][j] |= (1 << 1);
face[i][j - 1] |= (1 << 2);
face[i - 1][j] |= (1 << 3);
}
if(mp[i][j] == 'S')
{
face[i][j] = 15;
face[i + 1][j] |= (1 << 0);
face[i][j - 1] |= (1 << 1);
face[i - 1][j] |= (1 << 2);
face[i][j + 1] |= (1 << 3);
}
if(mp[i][j] == 'W')
{
face[i][j] = 15;
face[i][j - 1] |= (1 << 0);
face[i - 1][j] |= (1 << 1);
face[i][j + 1] |= (1 << 2);
face[i + 1][j] |= (1 << 3);
}
}
}
}
struct node{
int r, c, t;
node(int _r = 0, int _c = 0, int _t = 0) : r(_r), c(_c), t(_t) {}
bool operator < (node a) const
{
return t > a.t;
}
};
priority_queue<node> que;
int go[4][2] = {1, 0, 0, 1, -1, 0, 0, -1};
bool vis[MAXN][MAXN][4];
inline bool valid(int i, int j)
{
return (i <= n && i > 0 && j <= n && j > 0) && mp[i][j] != '#';
}
int bfs()
{
while(!que.empty()) que.pop();
memset(vis, 0, sizeof(vis));
//int head, tail;
//head = tail = 0;
que.push(node(sr, sc, 0));
while(!que.empty())
{
node u = que.top(), v; que.pop();
if(u.r == er && u.c == ec) return u.t;
// cout << u.r << " " << u.c << " " << u.t << endl;
if(!vis[u.r][u.c][(u.t + 1) & 3])//原地不动
{
vis[u.r][u.c][(u.t + 1) & 3] = 1;
que.push(node(u.r, u.c, u.t + 1));
}
for(int i = 0; i < 4; i++)
{
v.r = u.r + go[i][0];
v.c = u.c + go[i][1];
v.t = u.t + 1;
if(!valid(v.r, v.c)) continue;
if(face[v.r][v.c] & (1 << (u.t & 3))) // 目标格子被监控
{
v.t += 2;
if(vis[v.r][v.c][v.t & 3]) continue;
vis[v.r][v.c][v.t & 3] = 1;
que.push(v);
}
else
{
if(face[u.r][u.c] & (1 << (u.t & 3))) // 当前格子被监控
{
v.t += 2;
if(vis[v.r][v.c][v.t & 3]) continue;
vis[v.r][v.c][v.t & 3] = 1;
que.push(v);
}
else
{
if(vis[v.r][v.c][v.t & 3]) continue;
vis[v.r][v.c][v.t & 3] = 1;
que.push(v);
}
}
}
}
return -1;
}
int main()
{
int T, kase = 1;
cin >> T;
while(T--)
{
scanf("%d", &n);
for(int i = 1; i <= n; i++)
{
scanf("%s", mp[i] + 1);
for(int j = 1; j <= n; j++)
{
if(mp[i][j] == 'M')
sr = i, sc = j;
if(mp[i][j] == 'T')
er = i, ec = j;
}
}
init();
int ans = bfs();
printf("Case #%d: %d\n", kase++, ans);
}
return 0;
}