注意到k特别小,所以可以分别从@和有宝藏的房间出发,记录下到其他有宝藏的房间或者@的最短路长度。然后K!次枚举去这些宝藏房间的顺序即可
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
#define MAXN 110
int n,m,t,ans;
char g[MAXN][MAXN];
int dis[10][10],p[10][2],vis[MAXN][MAXN];
struct node
{
int x,y;
};
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
void bfs(int s)
{
node now,tmp;
now.x=p[s][0],now.y=p[s][1];
queue<node> q;
q.push(now);
memset(vis,-1,sizeof(vis));
vis[now.x][now.y]=0;
while (!q.empty())
{
now=q.front();
q.pop();
int x=now.x,y=now.y;
for (int i=0;i<4;i++)
{
int tx=x+dir[i][0];
int ty=y+dir[i][1];
if (tx<0||tx>=n||ty<0||ty>=m||g[tx][ty]=='#'||vis[tx][ty]!=-1) continue;
vis[tx][ty]=vis[x][y]+1;
tmp.x=tx,tmp.y=ty;
q.push(tmp);
}
}
for (int i=0;i<=t;i++)
dis[s][i]=vis[p[i][0]][p[i][1]];
}
bool ok[10];
void dfs(int u,int dep,int len)
{
if (dep==t)
{
if (ans==-1||ans>len) ans=len;
return;
}
for (int i=1;i<=t;i++)
if (!ok[i]&&dis[u][i]!=-1)
{
ok[i]=1;
dfs(i,dep+1,len+dis[u][i]);
ok[i]=0;
}
}
int main()
{
//freopen("/home/moor/Code/input","r",stdin);
while (scanf("%d%d",&n,&m)!=-1)
{
if (!n&&!m) break;
for (int i=0;i<n;i++)
{
scanf("%s",g[i]);
for (int j=0;j<m;j++)
if (g[i][j]=='@')
p[0][0]=i,p[0][1]=j;
}
int flag=1;
scanf("%d",&t);
for (int i=1;i<=t;i++)
{
int x,y;
scanf("%d%d",&x,&y);
x--,y--;
p[i][0]=x,p[i][1]=y;
if (g[x][y]=='#') flag=0;
}
if (!flag)
{
printf("-1\n");
continue;
}
for (int i=0;i<=t;i++)
bfs(i);
ans=-1;
dfs(0,0,0);
printf("%d\n",ans);
}
return 0;
}