题目链接
题解
- 由于$p$很小,所以可以考虑将当前有哪些钥匙用二进制压缩,作为一层状态,这样最多有$n*m*2^p$个状态
- 这样处理过后在图上$bfs$求解即可,注意一个房间可以能有多个钥匙
查看代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> p;
const int maxn = 1e5+5;
const int mod = 1e9+7;
ll qpow(ll a,ll b){ll res=1;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
int d[11][11][2100];
int key[11][11];
bool vis[11][11][2100];
map<pair<p,p>,int>mp;
int n,m,k;
struct node
{
int x,y,sta,cost;
node(int a,int b,int c,int d):x(a),y(b),sta(c),cost(d){}
};
int dir[][2]={0,1,0,-1,1,0,-1,0};
void bfs()
{
queue<node>q;
q.push(node(1,1,0,0));
vis[1][1][0]=1;
while(!q.empty()){
node now = q.front();
q.pop();
if(now.x==n&&now.y==m){
printf("%d\n",now.cost);
return;
}
for(int i = 0;i < 4;++i){
int x = now.x+dir[i][0];
int y = now.y+dir[i][1];
if(x<1||x>n||y<1||y>m)continue;
int tmp=-1;
auto ite = mp.find(make_pair(make_pair(now.x,now.y),make_pair(x,y)));
if(ite!=mp.end()){
tmp = ite->second;
if(!((now.sta>>tmp)&1))
continue;
}
int s = now.sta;
if(key[x][y]!=0)
s = now.sta|(key[x][y]);
if(vis[x][y][s])continue;
vis[x][y][s]=1;
q.push(node(x,y,s,now.cost+1));
}
}
printf("-1\n");
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("simple.in", "r", stdin);
freopen("simple.out", "w", stdout);
#endif
scanf("%d%d%d",&n,&m,&k);
int p;
scanf("%d",&p);
for(int i = 1,a,b,c,d,e;i <= p;++i){
scanf("%d%d%d%d%d",&a,&b,&c,&d,&e);
mp[make_pair(make_pair(a,b),make_pair(c,d))]=e;
mp[make_pair(make_pair(c,d),make_pair(a,b))]=e;
}
int fd;
scanf("%d",&fd);
for(int i = 1,a,b,c;i <= fd;++i){
scanf("%d%d%d",&a,&b,&c);
key[a][b]|=(1<<c);
}
bfs();
return 0;
}