題目傳送門
題目:
的迷宮,相鄰的位置之間可能有牆、有門或者沒有限制。鑰匙的種類是 。
你最初在 這個位置。
可以上下左右移動,
你移動的方向上如果有牆,則不能在這個方向移動。
你移動的方向上如果有門,則需要有和這個門匹配的鑰匙才能走。
有的位置擺放着鑰匙,你移動到該位置後可以拿到鑰匙。
問到達 位置的最小路程。
數據範圍: 。
題解:
假如只有牆沒有門,那就是 。
加上了門這個限制之後,把鑰匙狀壓就好了。
感受:
我好菜啊,沒想到狀壓。
代碼:
#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 ;
}