题目
注意到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; }