拯救大兵瑞恩node
思路:鑰匙種類p = 10,咱們能夠擁有不一樣種類鑰匙,經過這個咱們能夠把圖分紅2^p層,表示擁有不一樣種類鑰匙的狀況。ios
#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\n", ans == 1e9 ? -1 : ans); } } int main(){ solve(); //cout << "not error" << endl; return 0; }