传送门
I think
分层图问题.p枚钥匙是否拿到共有2^p种状态,用二进制表示,对于每一种状态建立分层图广搜求解.
许久不打BFS生疏了.
Code
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int sm = 11;
const int sn = 1<<15;
int N,M,K,S,mx,Ans;
int a[sm][sm][sm][sm];
int d[sn][sm][sm],vis[sn][sm][sm];
int key[sm][sm];
struct status {
int x,y,z;
}now;
int xz[4] = {-1,1,0,0};
int yz[4] = {0,0,-1,1};
int Max(int x,int y) { return x>y?x:y; }
int Min(int x,int y) { return x<y?x:y; }
int main() {
int u,v,x,y,g;
scanf("%d%d%d",&N,&M,&K);
scanf("%d",&K);
for(int i=1;i<=K;++i) {
scanf("%d%d%d%d%d",&u,&v,&x,&y,&g);
if(!g) a[x][y][u][v]=a[u][v][x][y]=-1;
else {
a[u][v][x][y]|=1<<g;
a[x][y][u][v]=a[u][v][x][y];
}
}
scanf("%d",&S);
for(int i=1;i<=S;++i) {
scanf("%d%d%d",&u,&v,&g);
key[u][v]|=1<<g;
mx=Max(mx,g);
}
memset(d,0x3f,sizeof(d));
queue<status>q;
q.push((status){ 1,1,0 });
d[0][1][1]=0;
while(!q.empty()) {
now = q.front(),q.pop();
vis[now.z][now.x][now.y]=0;
for(int i=0;i<4;++i) {
u=now.x+xz[i];
v=now.y+yz[i];
if(u>0&&v>0&&u<=N&&v<=M&&d[now.z][u][v]>d[now.z][now.x][now.y]+1&&a[now.x][now.y][u][v]!=-1&&(now.z&a[now.x][now.y][u][v])==a[now.x][now.y][u][v]) {
d[now.z|key[u][v]][u][v]=d[now.z][u][v]=d[now.z][now.x][now.y]+1;
if(!vis[now.z|key[u][v]][u][v]) {
vis[now.z|key[u][v]][u][v]=1;
q.push((status) { u,v,now.z|key[u][v] });
}
}
}
}
Ans = 0x3f3f3f3f;
for(int i=0;i<=(1<<mx+1);++i)
Ans=Min(Ans,d[i][N][M]);
if(Ans==0x3f3f3f3f) puts("-1");
else printf("%d\n",Ans);
return 0;
}