拯救大兵瑞恩 HDU - 4845 | bfs + 状压

题意:
1944年,特种兵麦克接到国防部的命令,要求立即赶赴太平洋上的一个孤岛,营救被敌军俘虏的大兵瑞恩。瑞恩被关押在一个迷宫里,迷宫地形复杂,但是幸好麦克得到了迷宫的地形图。
迷宫的外形是一个长方形,其在南北方向被划分为N行,在东西方向被划分为M列,于是整个迷宫被划分为N*M个单元。我们用一个有序数对(单元的行号,单元的列号)来表示单元位置。南北或东西方向相邻的两个单元之间可以互通,或者存在一扇锁着的门,又或者存在一堵不可逾越的墙。迷宫中有一些单元存放着钥匙,并且所有的门被分为P类,打开同一类的门的钥匙相同,打开不同类的门的钥匙不同。
   大兵瑞恩被关押在迷宫的东南角,即(N,M)单元里,并已经昏迷。迷宫只有一个入口,在西北角,也就是说,麦克可以直接进入(1,1)单元。另外,麦克从一个单元移动到另一个相邻单元的时间为1,拿取所在单元的钥匙的时间以及用钥匙开门的时间忽略不计。
   你的任务是帮助麦克以最快的方式抵达瑞恩所在单元,营救大兵瑞恩。
分析:
这个状压体现在key上 我i们用把key状压一下 就能记录到一个点时 已经拥有的key的种类
ban[x1][y1][x2][y1]记录两个点之间的状态 是门 还是墙 还是啥都没有
inc[x][y]记录这个点所存储的钥匙 (可能不止一个 所以要用二进制)
vis[x][y][key] 标记当前点 在拥有的钥匙种类为key时是否走过
代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
//typedef __int128 lll;
#define close() ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(a) cout << "debug :" << a << endl
#define fi first
#define se second
const int maxn = 1e6;
const int inf = 0x3f3f3f3f;
struct node
{
    int x, y, key, step;
    node(int a = 0, int b = 0, int c = 0, int d = 0) : x(a), y(b), key(c), step(d){}
};
int vis[20][20][10000], wall[20][20][20][20];
int key[20][20];
int n, m, p;
int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
void init()
{
    mem(wall, -1), mem(vis, 0), mem(key, 0);
}

int bfs()
{
    queue<node> q;
    q.push(node(1, 1, key[1][1], 0));
    vis[1][1][key[1][1]] = 1;
    while(!q.empty())
    {
        node now = q.front(); q.pop();
        if(now.x == n && now.y == m) return now.step;
        for(int i = 0; i < 4; i++)
        {
            int x = now.x + dir[i][0], y = now.y + dir[i][1];
            if(x < 1 || x > n || y < 1 || y > m || !wall[now.x][now.y][x][y]) continue;
            if(wall[now.x][now.y][x][y] == -1 || (now.key & (1 << (wall[now.x][now.y][x][y] - 1))))
            {
                int nexkey = now.key | key[x][y];
                if(vis[x][y][nexkey]) continue;
                vis[x][y][nexkey] = 1;
                node nex = node(x, y, nexkey, now.step + 1);
                q.push(nex);
            }

        }
    }
    return -1;
}

int main()
{
    while(cin >> n >> m >> p)
    {
        int k;cin >> k;
        init();
        while(k--)
        {
            int x1, y1, x2, y2, wal;
            cin >> x1 >> y1 >> x2 >> y2 >> wal;
            wall[x1][y1][x2][y2] = wall[x2][y2][x1][y1] = wal;
        }
        cin >> k;
        while(k--)
        {
            int x, y, ke;
            cin >> x >> y >> ke;
            key[x][y] |= (1 << (ke - 1));
        }
        cout << bfs() << endl;
    }
    
}