E. Maze
题意:
一个迷宫,有 (p) 种钥匙散落,起点 ((1,1)) , 终点 ((n,m))
会有一些墙和门, 一种类型的门需要对应的钥匙才能打开,开门不消耗钥匙
每移动一个需要花费 (1) 单位的时间,问最少需要多少时间到终点
(p le 10) ,(n,m le 50)
思路:
直接来一手状态压缩,搞一个广搜就ok了
#include<bits/stdc++.h>
using namespace std;
int f[60][60][1200];
int key[60][60];
int vis[60][60][1200];
int mp[60][60][4];
const int dx[] = { 1,0,-1,0 };
const int dy[] = { 0,1,0,-1 };
int getdir(int ax, int ay, int bx, int by) {
for (int i = 0; i < 4; i++) {
if (ax + dx[i] == bx and ay + dy[i] == by)return i;
}
}
int n, m, q, s;
int main() {
#ifdef ONLINE_JUDGE
#else
freopen("in.txt","r",stdin);
#endif
while (~scanf("%d%d%d", &n, &m, &q)) {
scanf("%d", &s);
memset(mp, -1, sizeof mp);
memset(vis, 0, sizeof vis);
memset(key, 0, sizeof key);
memset(f, 0, sizeof f);
while (s--) {
int ax, ay, bx, by, ty;
scanf("%d%d%d%d%d", &ax, &ay, &bx, &by, &ty);
mp[ax][ay][getdir(ax, ay, bx, by)] = ty;
mp[bx][by][getdir(bx, by, ax, ay)] = ty;
}
scanf("%d", &s);
while (s--) {
int x, y, ty;
scanf("%d%d%d", &x, &y, &ty);
key[x][y] |= (1 << ty) ;
}
int ans = 0x7fffffff;
queue<tuple<int, int, int, int> >Q;
Q.push(tuple<int, int, int, int>{ 1,1,key[1][1],0 });
vis[1][1][key[1][1]] = 1;
while (not Q.empty()) {
auto tp = Q.front(); Q.pop();
int x = get<0>(tp), y = get<1>(tp), state = get<2>(tp), dis = get<3>(tp);
//printf("{%d, %d} state: %d dis : %d
", x, y, state, dis);
if (x == n and y == m) {
ans = dis;
break;
}
for (int i = 0; i < 4; i++) {
int nx = x + dx[i], ny = y + dy[i];
if (nx < 1 or nx > n or ny < 1 or ny > m or mp[x][y][i] == 0)continue;
if (mp[x][y][i] > 0 and (state & (1 << mp[x][y][i])) == 0)continue;
if (!vis[nx][ny][state | key[nx][ny]]) {
Q.push(tuple<int, int, int, int>{ nx,ny,state | key[nx][ny], dis + 1 });
vis[nx][ny][state | key[nx][ny]] = 1;
}
}
}
if (ans == 0x7fffffff)ans = -1;;
printf("%d
", ans);
}
}