现在的位置: 首页 > 综合 > 正文

ZOJ 3652 Maze 优先队列 模拟

2018年04月25日 ⁄ 综合 ⁄ 共 2147字 ⁄ 字号 评论关闭

题意:有n*m(1 <= n m <= 50)的格子,-1代表不能走的地方,0代表空地,整数k(1<=k<=5)代表当前格子被k号怪物控制,但是每个怪物不一定在自己

         控制的范围内,一个人从给定的源点走到终点,每回合能走l移动值(1<=l<=10)块空地(如果k号怪物被打死了那么k号怪物控制的范围视为空地),

         如果走到一个编号问k且k号怪物还没死的空地,那么移动值立刻减为0,问最少要几个回合能走到终点。

题解:比赛的时候已经想到了四维记录状态[i][j][k][l]表示到达i j 位置打死怪物的状态为 k 剩余步数为 l 的最小回合数,但是更新时候的一个状态被我搞没了,

          一直在wa,比赛之后也wa了好久,还是自己的模拟功力不够吧唉,伤心……


Sure原创,转载请注明出处。

#include <iostream>
#include <cstdio>
#include <memory.h>
#include <queue>
using namespace std;
const int inf = 1 << 29;
const int maxn = 52;
const int maxk = 7;
const int maxl = 12;
const int move[4][2] = {{-1,0},{0,1},{1,0},{0,-1}};
struct ddd
{
    int x,y;
    int st,le;
    int turn;
    bool operator < (const ddd &other) const
    {
        if(turn == other.turn)
        {
            return le < other.le;
        }
        return turn > other.turn;
    }
};
int mon[maxn][maxn],map[maxn][maxn];
bool vis[maxn][maxn][1 << maxk][maxl];
priority_queue <ddd> Q;
int k,m,n,l,sx,sy,ex,ey;

void read()
{
    memset(vis,false,sizeof(vis));
    memset(mon,0,sizeof(mon));
    for(int i=1;i<=m;i++)
    {
        for(int j=1;j<=n;j++)
        {
            scanf("%d",&map[i][j]);
        }
    }
    scanf("%d",&k);
    int x,y;
    for(int i=1;i<=k;i++)
    {
        scanf("%d %d",&x,&y);
        mon[x][y] = i;
    }
    scanf("%d %d %d %d",&sx,&sy,&ex,&ey);
    return;
}

bool judge(int x,int y)
{
    if(x >= 1 && y >= 1 && x <= m && y <= n && map[x][y] != -1)
    {
        return true;
    }
    return false;
}

void bfs()
{
    if(sx == ex && sy == ey)   //源点和终点重合
    {
        puts("0");
        return;
    }
    int res = -1;
    while(!Q.empty()) Q.pop();
    ddd cur,tmp;
    tmp.x = sx;
    tmp.y = sy;
    tmp.st = 0;
    tmp.le = 0;
    tmp.turn = 0;
    vis[sx][sy][0][0] = true;
    Q.push(tmp);  //加入起始状态
    while(!Q.empty())
    {
        cur = Q.top();
        Q.pop();
        if(cur.x == ex && cur.y == ey)
        {
            res = cur.turn;
            break;
        }
        if(cur.le == 0)  //开始时我把到达每个点剩余步数为0的状态扔掉了……
        {
            cur.turn++;
            cur.le = l;
            if(vis[cur.x][cur.y][cur.st][cur.le] == false)
            {
                vis[cur.x][cur.y][cur.st][cur.le] = true;
                Q.push(cur);
            }
            continue;
        }
        for(int i=0;i<4;i++)
        {
            int xx = cur.x + move[i][0];
            int yy = cur.y + move[i][1];
            if(judge(xx , yy))
            {
                int ss,tt,ll;
                if(map[xx][yy] == 0 || cur.st & (1 << (map[xx][yy] - 1)))
                {
                    ss = cur.st;
                    if(mon[xx][yy])
                    {
                        ss |= (1 << (mon[xx][yy] - 1));
                    }
                    tt = cur.turn;
                    ll = cur.le - 1;
                }
                else
                {
                    if(mon[xx][yy] == 0)
                    {
                        ss = cur.st;
                        tt = cur.turn;
                        ll = 0;
                    }
                    else
                    {
                        ss = cur.st | (1 << (mon[xx][yy] - 1));
                        tt = cur.turn;
                        ll = 0;
                    }
                }
                if(vis[xx][yy][ss][ll] == false)
                {
                    vis[xx][yy][ss][ll] = true;
                    tmp.x = xx;
                    tmp.y = yy;
                    tmp.st = ss;
                    tmp.turn = tt;
                    tmp.le = ll;
                    Q.push(tmp);
                }
            }
        }
    }
    if(res == -1) puts("We need God's help!");
    else printf("%d\n",res);
    return;
}

int main()
{
    while(~scanf("%d %d %d",&m,&n,&l))
    {
        read();
        bfs();
    }
    return 0;
}

抱歉!评论已关闭.