题意: 在密室中,有n个宝物,n<=4; 问从起点开始找到所有宝物的最短时间。
题解:把标记数组多开一维,用二进制记录钥匙拿到没,4把钥匙 就是 1 1 1 1.==15;
暴力bfs 取最短就行
复杂度 16*n^2;
#include<iostream>
#include<string>
#include<stdio.h>
#include<string.h>
#include<map>
#include<math.h>
#include<queue>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn=105;
const int inf = 0xffffff;
char ma[maxn][maxn];
int vis[maxn][maxn][16];
int dir[4][2]={1,0,0,1,0,-1,-1,0};
int n,m,k,ans;
struct node{
int x,y,step,key;
}u,v,st;
int judge(int x,int y){
if(x<1||y<1||x>n||y>m) return 0;
if(ma[x][y]=='#') return 0;
return 1;
}
int bfs(){
memset(vis,0,sizeof(vis));
st.key=0;
st.step=0;
vis[st.x][st.y][st.key]=1;
queue<node>que;
que.push(st);
while(!que.empty()){
u=que.front();
que.pop();if(u.key==(1<<k)-1) ans=min(ans,u.step);
for(int i=0;i<4;++i){
v.x=u.x+dir[i][0];
v.y=u.y+dir[i][1];
v.key=u.key;
v.step=u.step+1;
if(judge(v.x,v.y)&&!vis[v.x][v.y][v.key]){
if(ma[v.x][v.y]==1&&!(v.key&1)){
v.key+=1;
vis[v.x][v.y][v.key]=1;
que.push(v);
}else if(ma[v.x][v.y]==2&&(v.key&&2)){
v.key+=2;
vis[v.x][v.y][v.key]=1;
que.push(v);
}else if(ma[v.x][v.y]==4&&!(v.key&4)){
v.key+=4;
vis[v.x][v.y][v.key]=1;
que.push(v);
}else if(ma[v.x][v.y]==8&&!(v.key&8)){
v.key+=8;
vis[v.x][v.y][v.key]=1;
que.push(v);
}else{
vis[v.x][v.y][v.key]=1;
que.push(v);
}
}
}
}
return 0;
}
int main(){
int a,b;
while(scanf("%d %d",&n,&m)&&(n+m)){
int f=1;
ans=inf;
for(int i=1;i<=n;++i) scanf("%s",ma[i]+1);
for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)if(ma[i][j]=='@') st.x=i,st.y=j;
scanf("%d",&k);
for(int i=1;i<=k;++i){
scanf("%d %d",&a,&b);
if(ma[a][b]!='#') ma[a][b]=1<<(i-1);
else f=0;
}
if(f==0) {printf("-1\n");continue;}
bfs();
if(ans==inf) printf("-1\n");
else printf("%d\n",ans);
}
return 0;
}