zoukankan      html  css  js  c++  java
  • 【单向BFS】Escape HDU

    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;
    }
    
  • 相关阅读:
    POJ2888 Magic Bracelet [矩阵快速幂+Burnside+欧拉函数]
    数列的 GCD [计数问题]
    com组件的注册
    WCF 传输和接受大数据
    数据库中已存在名为 'View_Business' 的对象。
    windows 两个用户,默认其中一个用户登录
    用C#读取,写入ini文件
    小心得,关于串口
    未能加载文件或程序集"Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad
    无法激活服务,因为它不支持 ASP.NET 兼容性
  • 原文地址:https://www.cnblogs.com/streamazure/p/13374167.html
Copyright © 2011-2022 走看看