Escape HDU - 3533
题意:
小A要从((0,0))逃到((n,m)),他的精力值为(d),每秒可以向东南西北四个方向走一格,或保持原地不动。但无论他是否移动,精力值每秒都会损失1点。路上他会遇到炮塔射击。给定(k)座炮塔的射击方向、射击间隔、子弹速度、坐标。第0秒小A开始逃跑,且所有炮塔开始射击。当小A被子弹击中或精力值耗尽,即失败。问小A能否抵达终点,若能,输出最小步数。
注意:
1.当小A与子弹在同一格,且该格是子弹的终点时,才算是被击中;如果子弹仅是经过了小A所在格子,不算被击中。
2.炮塔所在位置不能走。
3.炮塔会挡住射向它的子弹,但不会被摧毁。
4.子弹与子弹之间互不影响。
思路:
以人为对象进行BFS。判断条件即走到新格子时是否会恰好遇到子弹。根据题意,只需要判断新格子向四个方向延伸后分别所遇到的第一座炮塔即可。
子弹的判定有点复杂,详见注释,其他没啥难点。
int n, m, k, d;
int dx[] = { 0,1,0,-1,0 };
int dy[] = { 1,0,-1,0,0 };
struct Castle {
char dir;
int t;
int v;
bool castle;
}Map[105][105];
struct node {
int x, y;
int step;
};
bool vis[105][105][105];
//vis[x][y][time]
//time时刻的格子(x,y)只能访问一次
int bfs() {
queue<node> q;
q.push(node{ 0,0,0 });
vis[0][0][0] = true;
while (!q.empty()) {
node temp = q.front();
q.pop();
if (temp.step > d) return 0;
if (temp.x == n && temp.y == m) return temp.step;
for (int i = 0; i < 5; i++) {
int nx = temp.x + dx[i];
int ny = temp.y + dy[i];
int nstep = temp.step + 1;
if (nx<0 || ny<0 || nx>n || ny>m) continue;
if (Map[nx][ny].castle) continue;
if (vis[nx][ny][nstep]) continue;
int safe = 1;
//判断新格子是否会被射击
int N = nx, S = nx, W = ny, E = ny;
for(int N=nx-1;N>=0;N--) {
if (N < 0) break;
if (Map[N][ny].castle) {
if (Map[N][ny].dir != 'S') break;
int dis = N - nx;
//人与炮台的距离
if (dis % Map[N][ny].v != 0) break;
//如果不能整除速度,则子弹无法恰好抵达这个位置,安全
int timee = nstep - dis / Map[N][ny].v;
//能恰好抵达这个位置的子弹是在第timee秒射出的
if (timee < 0) break;
//是负数,不可能射出,安全
if (timee % Map[N][ny].t != 0) break;
//不是周期时间点,不可能射出,安全
safe = 0;
break;
}
}
if (!safe) continue;
for(int S=nx+1;S<=n;S++){
if (S > n) break;
if (Map[S][ny].castle) {
if (Map[S][ny].dir != 'N') break;
int dis = S - nx;
if (dis % Map[S][ny].v != 0) break;
int timee = nstep - dis / Map[S][ny].v;
if (timee < 0) break;
if (timee % Map[S][ny].t != 0) break;
safe = 0;
break;
}
}
if (!safe) continue;
for(int W=ny-1;W>=0;W--) {
if (W < 0) break;
if (Map[nx][W].castle) {
if (Map[nx][W].dir != 'E') break;
int dis = ny - W;
if (dis % Map[nx][W].v != 0) break;
int timee = nstep - dis / Map[nx][W].v;
if (timee < 0) break;
if (timee % Map[nx][W].t != 0) break;
safe = 0;
break;
}
}
if (!safe) continue;
for(int E=ny+1;E<=m;E++) {
if (E > m) break;
if (Map[nx][E].castle) {
if (Map[nx][E].dir != 'W') break;
int dis = E - ny;
if (dis % Map[nx][E].v != 0) break;
int timee = nstep - dis / Map[nx][E].v;
if (timee < 0) break;
if (timee % Map[nx][E].t != 0) break;
safe = 0;
break;
}
}
if (!safe) continue;
node now;
now.step = nstep;
now.x = nx;
now.y = ny;
q.push(now);
vis[nx][ny][nstep] = true;
}
}
return 0;
}
int main()
{
ios::sync_with_stdio(false);
//int t; cin >> t; while (t--) {
while(cin>>n>>m>>k>>d){
memset(Map, 0, sizeof(Map));
memset(vis, false, sizeof(vis));
for (int i = 1; i <= k; i++) {
char ch;
int t, v, x, y;
cin >> ch >> t >> v >> x >> y;
Map[x][y].dir = ch;
Map[x][y].t = t;
Map[x][y].v = v;
Map[x][y].castle = true;
}
int ans = bfs();
if (!ans) cout << "Bad luck!" << endl;
else cout << ans << endl;
}
return 0;
}