HDU 1885 Key Task(BFS + 状态压缩)

时间:2021-04-05 16:22:15

  做这个题的时候我给想简单了,还以为是个基础的广搜,后来发现搜索无法完成,因为vis的标记已经不能再使用了,因为一旦标记了,同一个结点不能走两次,而题目中有的时候有些点必须要走两次,甚至多次.

我就无从下手了,赛后看了题解才知道,每个点都有16个状态,用状态压缩可以来保存每个点的钥匙状态,开一个三维的vis数组就可以了,然后这就变成了普通的bfs...代码如下.

  还有就是,在一开始的时候我把状态记录错了,我竟然把|8写成了|16...给我整的一头雾水,后来才发现原来竟然是这里出错了..

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
/// b y r g
/// 1 2 3 4
/// 1 2 4 8
int n,m,vis[110][110][16],go[4][2] = {1,0,-1,0,0,1,0,-1};
char maps[110][110];
struct Pos
{
    int x,y,step,state;
    friend bool operator < (const Pos &a,const Pos &b)
    {
        return a.step > b.step;
    }
};
priority_queue<Pos> que;
Pos st,ex;
bool OK1(int x,int y)
{
    if(x>=0&&x<n&&y>=0&&y<m&&maps[x][y]!='#') return true;
    return false;
}
bool OK2(int i,int j,int s)
{
    if(maps[i][j]=='B'&&(s&1))
        return true;
    if(maps[i][j]=='Y'&&(s&2))
        return true;
    if(maps[i][j]=='R'&&(s&4))
        return true;
    if(maps[i][j]=='G'&&(s&8))
        return true;
    return false;
}
int bfs(Pos a)
{
    memset(vis,0,sizeof(vis));
    vis[a.x][a.y][a.state] = 1;
    while(!que.empty()) que.pop();
    que.push(a);
    while(!que.empty())
    {
        Pos now = que.top();
        que.pop();
        Pos nxt;
        for(int k = 0; k < 4; k++)
        {
            int i = now.x + go[k][0];
            int j = now.y + go[k][1];
            if(OK1(i,j))
            {
                if(OK2(i,j,now.state)&&!vis[i][j][now.state])
                {
                    vis[i][j][now.state]=1;
                    nxt.step = now.step + 1;
                    nxt.state = now.state;
                    nxt.x = i,nxt.y = j;
                    que.push(nxt);
                }
                else if(maps[i][j]=='b'&&!vis[i][j][now.state|1])
                {
                    vis[i][j][now.state|1] = 1;
                    nxt.step = now.step + 1;
                    nxt.state = now.state|1;
                    nxt.x = i,nxt.y = j;
                    que.push(nxt);
                }
                else if(maps[i][j]=='y'&&!vis[i][j][now.state|2])
                {
                    vis[i][j][now.state|2]=1;
                    nxt.step = now.step + 1;
                    nxt.state = now.state|2;
                    nxt.x = i,nxt.y = j;
                    que.push(nxt);
                }
                else if(maps[i][j]=='r'&&!vis[i][j][now.state|4])
                {
                    vis[i][j][now.state|4]=1;
                    nxt.step = now.step + 1;
                    nxt.state = now.state|4;
                    nxt.x = i,nxt.y = j;
                    que.push(nxt);
                }
                else if(maps[i][j]=='g'&&!vis[i][j][now.state|8])
                {
                    vis[i][j][now.state|8]=1;
                    nxt.step = now.step + 1;
                    nxt.state = now.state|8;
                    nxt.x = i,nxt.y = j;
                    que.push(nxt);
                }
                else if(maps[i][j]=='.'&&!vis[i][j][now.state])
                {
                    vis[i][j][now.state]=1;
                    nxt.step = now.step + 1;
                    nxt.state = now.state;
                    nxt.x = i,nxt.y = j;
                    que.push(nxt);
                }
                else if(maps[i][j]=='X')
                    return now.step+1;
            }
        }
    }
    return -1;
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        if(n == 0 && m == 0) break;
        for(int i = 0; i < n; i++)
            scanf("%s",maps[i]);
        ex.x = -1;
        for(int i = 0; i < n; i++)
        {
            for(int j = 0; j < m; j++)
            {
                if(maps[i][j] == '*')
                {
                    st.x = i,st.y = j;
                    st.step = 0,st.state = 0;
                }
                if(maps[i][j] == 'X')
                {
                    ex.x = i,ex.y = j;
                    ex.step = 0,ex.state = 0;
                }
            }
        }
        if(ex.x == -1)
        {
            puts("The poor student is trapped!");
            continue;
        }
        maps[st.x][st.y] = '.';
        int ans = bfs(st);
        if(ans == -1) puts("The poor student is trapped!");
        else printf("Escape possible in %d steps.\n",ans);
    }
    return 0;
}