Loading

E. Maze【2014上海邀请赛】

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\n", 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\n", ans);
	}
}
posted @ 2020-12-02 21:35  —O0oO-  阅读(79)  评论(0编辑  收藏  举报