【單向BFS】Escape HDU - 3533
阿新 • • 發佈:2020-07-24
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; }