题目链接
一道有着很多需要细节的地方需要注意的题,挺不错的。
这题的数据也是给的很好,然后讲一下题意吧。
题意:有一个N*N的网格,有起点M和终点T,我们从起点需要走到终点,每一步需要花费的时间是单位一。但是呢,我们不能被摄影机拍摄到,摄影机是在一秒内由某个方向旋转到另一个方向的,而人也是走到下一个点不是瞬时移动的,而是经过一秒的时间(延续性动作)走到下一个地点(只能朝东南西北——对应“右下左上”四个各自)的。并且如果我们被摄影机拍到了,我们移动所需要的时间就是3s,无论是开始被拍到还是移动到对应的位置的过程中的时候被拍到。另外,我们可以选择躲进箱子里,那么就是在原地待1s。“they will rotate 90 degree clockwisely. Every camera's sight range is 2, which means that if Matt is in the same grid as the camera, or in the grid that the camera is facing”题目中其实把摄影机的拍摄范围说的很清楚,自己所在的点,以及它面对的点,所以这个距离2指的是本身以及向外一个单位长度。当然,随着时间的流逝,摄影机也是跟着顺时针旋转的。
思路:很显然的是一个BFS的过程。但是,维护其中的状态我们需要进行思考了。我们从目前的点(x, y)花费时间z,我们定义这样的一个三元组(x, y, z)。下一个目标的点是(xx, yy, zz)。也就是我们从(x, y)走到(xx, yy)。首先,如果我们要往下一格走,我们首先考虑的是我们可不可以先“龟缩”熬一回合呢?好,如果当前情况下,我们没有“龟缩”过,可行,存一下这个状态。再者,我们强制就是要往下走,好,如果现在情况特殊,被摄影机拍到了,那么我们就是要浪费3s来解决问题了;不然,如果没有被摄影机拍到,我们可以直接走下去,耗费1s。
如何检验是否被摄影机拍到呢?如果说,我们恰好遇上我们的(x, y)的点在z时刻是被摄影机拍到的,那么就是被摄影机拍到了的;或者说,(xx, yy)的点,由于我们是在z时间间隔里移动的,「“for every second”,指的是每一个时间间隔」所以,如果说如果第z秒的时候,是被拍到的,说明就是被拍到了的,此处是指时间间隔,第一秒呢,实际上就是[0, 1](闭区间)这样的一个间隔时间。
大体上的问题是解决了的,接下去为了时间是最短的,我们直接利用优先队列来操作就可以了的。
附上一组测试数据
1
4
MS#.
..#.
.#E.
...T
ans == 7
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int dir[4][2] =
{
-1, 0, //N
0, 1, //E
1, 0, //S
0, -1 //W
};
const int id[4] = { 0, 1, 2, 3 };
map<char, int> str;
const int maxN = 505;
int N, sx, sy;
inline bool In_Map(int x, int y) { return x >= 1 && y >= 1 && x <= N && y <= N; }
char mp[maxN][maxN];
bool camera[maxN][maxN][4], vis[maxN][maxN][4]; //是否会被摄影机抓拍到
struct node
{
int x, y, z;
node(int a=0, int b=0, int c=0):x(a), y(b), z(c) {}
friend bool operator < (node e1, node e2) { return e1.z > e2.z; }
};
inline int bfs()
{
priority_queue<node> Q;
Q.push(node(sx, sy, 0));
vis[sx][sy][0] = true;
node now;
int x, y, xx, yy, z, zz;
while(!Q.empty())
{
now = Q.top(); Q.pop();
x = now.x; y = now.y; z = now.z;
if(mp[x][y] == 'T') return z;
if(!vis[x][y][(z + 1) % 4])
{
vis[x][y][(z + 1) % 4] = true;
Q.push(node(x, y, z + 1));
}
for(int i=0; i<4; i++)
{
xx = x + dir[i][0]; yy = y + dir[i][1]; zz = z % 4;
if(!In_Map(xx, yy) || mp[xx][yy] == '#') continue;
if(camera[x][y][zz] || camera[xx][yy][zz])
{
zz = (z + 3) % 4;
if(!vis[xx][yy][zz])
{
vis[xx][yy][zz] = true;
Q.push(node(xx, yy, z + 3));
}
}
else
{
zz = (z + 1) % 4;
if(!vis[xx][yy][zz])
{
vis[xx][yy][zz] = true;
Q.push(node(xx, yy, z + 1));
}
}
}
}
return -1;
}
inline void init()
{
for(int i=1; i<=N; i++)
{
for(int j=1; j<=N; j++)
{
for(int k=0; k<4; k++) camera[i][j][k] = vis[i][j][k] = false;
}
}
}
int main()
{
str['N'] = 0; str['E'] = 1; str['S'] = 2; str['W'] = 3;
int T; scanf("%d", &T);
for(int Cas=1; Cas <= T; Cas++)
{
scanf("%d", &N);
init();
for(int i=1, fir_dir, xx, yy; i<=N; i++)
{
scanf("%s", mp[i] + 1);
for(int j=1; j<=N; j++)
{
if(mp[i][j] == 'M') { sx = i; sy = j; }
else if(mp[i][j] == 'T') { }
else if(mp[i][j] >= 'A' && mp[i][j] <= 'Z')
{
fir_dir = id[str[mp[i][j]]];
for(int k=0, nk; k<4; k++)
{
nk = (k + fir_dir) % 4;
xx = i + dir[nk][0]; yy = j + dir[nk][1];
camera[xx][yy][k] = true;
camera[i][j][k] = true;
}
}
}
}
printf("Case #%d: %d\n", Cas, bfs());
}
return 0;
}