1. 程式人生 > 實用技巧 >【單向BFS】Escape HDU - 3533

【單向BFS】Escape HDU - 3533

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;
}