zoukankan      html  css  js  c++  java
  • zoj3652 Maze

    题意:给定一个n * m  的矩阵(迷宫),-1 表示该位置不能通过, 1 ~ 5 表示该位置被第i个怪控制, 0 表示该位置不被任何怪控制
    给定起点和终点, 问Celica 最少需要多少回合才能通过。当然,还有很多限制条件:
    1)每一个回合, Celica  的初始行动值为L, 没移动一个位置,行动值-1, 当行动值减为0, 则开始下一个回合
    2)一旦踏入怪的所在位置,则立即会将怪杀死,怪所控制的位置也就变为0了
    3)当移动到一个怪所控制的位置,行动立即减为0
    4)每到达一个位置,首先变化的是行动值, 这就意味着,如果踏入一个怪所在的位置,而且该位置是被怪所控制的情况下,那么行动值先变为0,再将怪杀死
    5)怪不一定在它控制的位置
    6)起点一定没有怪, 但可能被某一个怪控制
     
    分析:除了弄清题意外,首先应该注意到的是数据范围, n <= 50, 这种地图略大, 且求的是最小值,一般用的是广搜。 当然,如果地图再小一点,也可能是用IDA*等搜索方法解决。
    不过,我首先想到的是用IDA, 通过限制回合数,深搜来求得最小回合数。不过没想到更好的剪枝方法。 为什么没想到广搜呢?其实是因为每移动一步,地图可能改变,那每一个状态都要将整个地图保存么?这个问题一开始没
    想通, 所以就没敲了。 后来突然想到,地图改变是因为可能是某些怪挂掉了,而且最多才五只怪。那么只要知道五只怪的存活情况,就知道当前的地图是怎么样的了。
    另外要考虑的问题就是,状态的表示了,表示一个唯一的状态。对于这种迷宫问题,首先就是考虑一个点是否只能走一次? 不是的,试想一下,是否存在一种情况,经过某一个点去杀一个怪,杀玩完再经过这个点去终点却存在最优值呢?
    答案是肯定的。所以,我们应该用vis[x][y][state] 标记经过该点时的状态, state 表示 五只怪的存活情况,如果第二次经过该点时state的值没变, 那么也就没必要将该点重新压入队列, 当然,这里说的是优先队列, 因为每一次的
    代价并非相等的
     
    zoj3652
    #include<iostream>
    #include<algorithm>
    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #include<vector>
    #include<queue>
    
    using namespace std;
    
    const int N = 50 + 10;
    
    int g[N][N];
    
    struct node
    {
        int t, mob, state;//t 表示回合数, mob 表示当前回合剩余行动值
        int x, y;
        node(){}
        node(int x, int y, int t, int mob, int state):x(x), y(y), t(t), mob(mob), state(state){}
        bool friend operator < (const node &a, const node &b)
        {
            if(a.t != b.t) return a.t > b.t;
            return a.mob < b.mob;
        }
    };
    
    priority_queue<node> Q;
    
    int n, m, L;
    bool vis[N][N][32];
    int mark[N][N];//标记该位置存在哪一个怪,-1表示不存在怪
    int si, sj, ei, ej;
    int dir[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
    
    int BFS()
    {
        while(!Q.empty())
            Q.pop();
        memset(vis, false, sizeof(vis));
        vis[si][sj][0] = true;
        Q.push(node(si, sj, 0, L, 0));
        while(!Q.empty())
        {
            node cur = Q.top();
            Q.pop();
            //cout << cur.x << ' ' << cur.y << ' ' << cur.t << ' ' << cur.mob << ' ' << cur.state << endl;
            if(cur.x == ei && cur.y == ej) 
            {
                if(cur.mob == L)
                    return cur.t;
                return cur.t + 1;
            }
            for(int k = 0; k < 4; ++k)
            {
                int x = cur.x + dir[k][0], y = cur.y + dir[k][1];
                if( x <= 0 || x > n || y <= 0 || y > m || g[x][y] == -1) continue;
                int mob = cur.mob - 1, state = cur.state;
                if(g[x][y] != 0)
                {
                    int t = g[x][y];
                    if(!(cur.state & (1 << (t - 1))))//判断怪是否已经被杀死
                        mob = 0;
                }    
                if(mark[x][y] >= 0) //怪所在的位置,则杀了怪,改变状态
                    state |= (1 << mark[x][y]);
    
                if(vis[x][y][state]) continue;
                int turn = cur.t;
                if(mob == 0)
                {
                    mob = L;
                    turn++;
                }
                vis[x][y][state] = true;
                Q.push(node(x, y, turn, mob, state));
            }
        }
        return -1;
    }
    int main()
    {
        int x, y;
        while(scanf("%d %d %d",&n, &m, &L) == 3)
        {
            for(int i = 1; i <= n; ++i)
                for(int j = 1; j <= m; ++j)
                    scanf("%d",&g[i][j]);
            memset(mark, -1, sizeof(mark));
            int k;
            scanf("%d", &k);
            for(int i = 0; i < k; ++i)
            {
                scanf("%d %d",&x, &y);
                mark[x][y] = i;
            }
            scanf("%d %d %d %d",&si, &sj, &ei, &ej);
            int ans = BFS();
            if(ans == -1) puts("We need God's help!");
            else
            printf("%d\n", BFS());
        }
        return 0;
    }
  • 相关阅读:
    20191005
    20191004-gugugu公告
    20191003
    10.2 一天
    考试总结 模拟$105$
    考试总结 模拟$104$
    考试总结 模拟$103$
    考试总结 模拟$102$
    考试总结 模拟$101$
    考试总结 模拟$100$
  • 原文地址:https://www.cnblogs.com/nanke/p/3011953.html
Copyright © 2011-2022 走看看