题目传送门
题目:
的迷宫,相邻的位置之间可能有墙、有门或者没有限制。钥匙的种类是 。
你最初在 这个位置。
可以上下左右移动,
你移动的方向上如果有墙,则不能在这个方向移动。
你移动的方向上如果有门,则需要有和这个门匹配的钥匙才能走。
有的位置摆放着钥匙,你移动到该位置后可以拿到钥匙。
问到达 位置的最小路程。
数据范围: 。
题解:
假如只有墙没有门,那就是 。
加上了门这个限制之后,把钥匙状压就好了。
感受:
我好菜啊,没想到状压。
代码:
#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 ;
}