拯救大兵瑞恩 HDU

拯救大兵瑞恩

思路:钥匙种类p = 10,我们可以拥有不同种类钥匙,通过这个我们可以把图分成2^p层,表示拥有不同种类钥匙的情况。

#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
#include <queue>

using namespace std;

const int N = 17;
int mv_x[] = {1, -1, 0, 0};
int mv_y[] = {0, 0, -1, 1};
int mp[N][N][N][N]; //地图相通情况
int key[N][N]; //钥匙分配情况
int step[1 << 11][N][N]; //分层图
int n, m, p, k, s; 

struct node{
    int x, y, lev;
};

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

void bfs(){
    queue<node > que;
    que.push({1, 1, 0});
    step[0][1][1] = 0;

    while(!que.empty()){
        node now = que.front();
        que.pop();
        int lev = now.lev;
        for(int p = 0; p < 4; ++p){
            int dx = now.x + mv_x[p];
            int dy = now.y + mv_y[p];
            //越界
            if(!check(dx, dy)) continue;
            //走过了
            if(step[lev][dx][dy] != -1) continue;
            int info = mp[now.x][now.y][dx][dy];
            //是墙
            if(info == 0) continue;
            //需要钥匙
            if(info != -1){
                //没这类钥匙
                if((lev | (1 << (info - 1))) != lev) continue;
                //有这类钥匙
                step[lev][dx][dy] = step[lev][now.x][now.y] + 1;
                que.push({dx, dy, lev});
                //下一步有钥匙
                if(key[dx][dy]){
                    //捡起钥匙
                    step[lev | key[dx][dy]][dx][dy] = step[lev][dx][dy];
                    que.push({dx, dy, lev | key[dx][dy]});
                }
            }else{
                //不需要钥匙
                step[lev][dx][dy] = step[lev][now.x][now.y] + 1;
                que.push({dx, dy, lev});
                //下一步有钥匙
                if(key[dx][dy]){
                    //捡起钥匙
                    step[lev | key[dx][dy]][dx][dy] = step[lev][dx][dy];
                    que.push({dx, dy, lev | key[dx][dy]});
                }                
            }
        }

    }
}

void solve(){

    while(~scanf("%d%d%d%d", &n, &m, &p, &k)){
        memset(mp, -1, sizeof(mp));
        memset(key, 0, sizeof(key));
        memset(step, -1, sizeof(step));
        
        int x1, x2, y1, y2, g;
        for(int i = 0; i < k; ++i){
            scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &g);
            mp[x1][y1][x2][y2] = g;
            mp[x2][y2][x1][y1] = g;
        }
        scanf("%d", &s);
        for(int i = 0; i < s; ++i){
            scanf("%d%d%d", &x1, &y1, &g);
            key[x1][y1] |= (1 << (g - 1));
        }

        bfs();
        int ans = 1e9;
        for(int i = 0; i <= 1030; ++i){

            if(step[i][n][m] == -1) continue;

            ans = min(ans, step[i][n][m]);
        }

        printf("%d
", ans == 1e9 ? -1 : ans);
    }
}

int main(){
    
    solve();    
    //cout << "not error" << endl;
    return 0;
}
原文地址:https://www.cnblogs.com/SSummerZzz/p/12986858.html