Libreoj6121 狀壓 + bfs

題目傳送門

題目:

\dpi{150} n * m 的迷宮,相鄰的位置之間可能有牆、有門或者沒有限制。鑰匙的種類是 p 。

你最初在 (1\;,\;1) 這個位置。

可以上下左右移動,

你移動的方向上如果有牆,則不能在這個方向移動。

你移動的方向上如果有門,則需要有和這個門匹配的鑰匙才能走。

有的位置擺放着鑰匙,你移動到該位置後可以拿到鑰匙。

問到達 (n\;,\;m) 位置的最小路程。

數據範圍:1 \leqslant n \;,\; m \;,\; p \leqslant 10 。

題解:

假如只有牆沒有門,那就是 bfs 。

加上了門這個限制之後,把鑰匙狀壓就好了。

感受:

我好菜啊,沒想到狀壓。

代碼:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll ;
typedef pair<int , int> pii ;
const int maxn = 15 ;
const int inf = 0x3f3f3f3f ;
int n , m , p , k , s ;
int row[4] = {-1 , 1 , 0 , 0} ;
int col[4] = {0 , 0 , -1 , 1} ;
int vis[1 << 10][12][12] ;
int door[12][12][12][12] ;
vector<int> key[12][12] ;
struct node
{
	int x , y ;
	int state , step ;
} ;
queue<node> q ;
int change(int state , int x , int y)
{
	for(auto v : key[x][y])  state |= (1 << (v - 1)) ;
	return state ;
}
bool ok(int state , int x , int y , int nx , int ny)
{
	int col = door[x][y][nx][ny] ;
	if(nx < 1 || nx > n || ny < 1 || ny > m)  return 0 ;
	if(col == 0)  return 0 ;
	if(col > 0 && (state & (1 << (col - 1))) == 0)  return 0 ;
	return 1 ;
}
void bfs()
{
	int state = 0 ;
	for(auto v : key[1][1])  state |= (1 << (v - 1)) ;
	q.push(node{1 , 1 , state , 0}) ;
	vis[state][1][1] = 0 ;
	while(!q.empty())
	{
		node u = q.front() ;
		q.pop() ;
		for(int i = 0 ; i < 4 ; i ++)
		{
			int nx = u.x + row[i] ;
			int ny = u.y + col[i] ;
			int nstate ;
			if(ok(u.state , u.x , u.y , nx , ny))
			{
				nstate = change(u.state , nx , ny) ;
				if(vis[nstate][nx][ny] > u.step + 1)
				{
					vis[nstate][nx][ny] = u.step + 1 ;
					q.push(node{nx , ny , nstate , u.step + 1}) ;
				}
			}
		}
	}
	int ans = inf ;
	for(int i = 0 ; i < (1 << 10) - 1 ; i ++)
	  ans = min(ans , vis[i][n][m]) ;
	if(ans == inf)  printf("-1\n") ;
	else  printf("%d\n" , ans) ;
}
int main()
{
	scanf("%d%d%d" , &n , &m , &p) ;
	scanf("%d" , &k) ;
	memset(door , -1 , sizeof(door)) ;
	memset(vis , inf , sizeof(vis)) ;
	for(int i = 1 ; i <= k ; i ++)
	{
		int x1 , y1 , x2 , y2 , g ;
		scanf("%d%d%d%d%d" , &x1 , &y1 , &x2 , &y2 , &g) ;
		door[x1][y1][x2][y2] = g ;
		door[x2][y2][x1][y1] = g ;
	}
	scanf("%d" , &s) ;
	for(int i = 1 ; i <= s ; i ++)
	{
		int x , y , q ;
		scanf("%d%d%d" , &x , &y , &q) ;
		key[x][y].push_back(q) ;
	}
	bfs() ;
	return 0 ;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章