胜利大逃亡(续)——BFS、状压

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1429
题目大意:就是从起点到终点,有路有墙有门有钥匙,钥匙能开对应的门,问能否到达终点,如果能就输出时间,如果不能就输出-1

题解:因为拿到钥匙回到对应门开门可能会走相同的路,所以呢不能单纯的只标记每块地板是否走过,要看该点在该状态(拿了多少钥匙)下是否走过,这里就还是用到了状态压缩,比上一题简单一点,所以写起来也没什么太大问题,嗯。

详解就不说了 去看这个嘛:https://blog.csdn.net/weixin_44049850/article/details/88073715

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <set>
#include <stack>
#include <map>
#define INF 0x3f3f3f3f

using namespace std;
typedef long long ll;

int n,m,t;
int sx,sy;
char mp[25][25];
bool vis[25][25][1050];

const int dir[4][2]={
        1,0,
        -1,0,
        0,1,
        0,-1
};
struct node{
    int x,y,state,s;
    node(int a=0,int b=0,int c=0,int d=0):x(a),y(b),state(c),s(d){}
};

bool InMap(int x,int y)
{
    return x>=1&&x<=n&&y>=1&&y<=m;
}

int bfs()
{
    memset(vis,false,sizeof(vis));
    queue<node>q;
    q.push(node(sx,sy,0,0));
    vis[q.front().x][q.front().y][0]=true;
    while(!q.empty())
    {
        for(int i=0;i<4;i++)
        {
            int tx=q.front().x+dir[i][0];
            int ty=q.front().y+dir[i][1];
            if(q.front().s>=t)
                return -1;
            if(!InMap(tx,ty)||mp[tx][ty]=='*'||vis[tx][ty][q.front().state])
                continue;
            if(mp[tx][ty]=='^')//走到终点
            {
                if(q.front().s+1<t)
                    return q.front().s+1;
                return -1;
            }
            if(mp[tx][ty]>='A'&&mp[tx][ty]<='J')//走到有锁的门
            {
                if(q.front().state>>(mp[tx][ty]-('A'-'a')-'a')&1)//如果有钥匙
                {
                    q.push(node(tx,ty,q.front().state,q.front().s+1));
                    vis[tx][ty][q.front().state]=true;
                }
                else//没有钥匙
                    continue;
            }
            else if(mp[tx][ty]>='a'&&mp[tx][ty]<='j')//走到有钥匙的点
            {
                if(q.front().state>>(mp[tx][ty]-'a')&1)//如果钥匙已经被拿了
                {
                    if(!vis[tx][ty][q.front().state])
                    {
                        q.push(node(tx,ty,q.front().state,q.front().s+1));
                        vis[tx][ty][q.front().state]=true;
                    }
                }
                else//钥匙没有被拿,拿上
                {
                    int state=q.front().state|1<<(mp[tx][ty]-'a');
                    q.push(node(tx,ty,state,q.front().s+1));
                    vis[tx][ty][state]=true;
                }
            }
            else//普通点
            {
                if(!vis[tx][ty][q.front().state])
                {
                    q.push(node(tx,ty,q.front().state,q.front().s+1));
                    vis[tx][ty][q.front().state]=true;
                }
            }
        }
        q.pop();
    }
    return -1;
}

int main()
{
    while(~scanf("%d%d%d",&n,&m,&t))
    {
        getchar();
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                scanf("%c",&mp[i][j]);
                if(mp[i][j]=='@')
                {
                    sx=i;
                    sy=j;
                    mp[i][j]='.';
                }
            }
            getchar();
        }
        printf("%d\n",bfs());
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44049850/article/details/88138064