注意,宝藏数最多只有4个,所有我们可以先用bfs搜索出宝藏加上起点两两间距离,然后在枚举走的顺序即可。
枚举顺序用next_permutation()函数比较方便
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <map> #include <queue> #include <vector> #include <cmath> #include <algorithm> using namespace std; struct node { int x,y; int step; }; struct pos{ int x,y; }G[1000]; int maze[105][105]; bool en[105][105]; bool vis[105][105]; int dir[105][105]; int n,m; int xx; int sx,sy; int ans=0; vector <pair<int,int> > A; int bfs(int x,int y,int ox,int oy) { memset(vis,0,sizeof(vis)); queue<node> q; node tmp; tmp.x=x,tmp.y=y; tmp.step=0; q.push(tmp); vis[x][y]=1; while(!q.empty()) { node tmp=q.front(); q.pop(); if(tmp.x==ox&&tmp.y==oy) return tmp.step; for(int i=-1;i<=1;i++) for(int j=-1;j<=1;j++) { if(i+j==-1||i+j==1) { int x=tmp.x+i,y=tmp.y+j; if(!vis[x][y]&&maze[x][y]!=-1&&x>=1&&y>=1&&x<=n&&y<=m) { vis[x][y]=1; node tt; tt.x=x,tt.y=y,tt.step=tmp.step+1; q.push(tt); } } } } return -1; } int main() { while(scanf("%d%d",&n,&m)&&(n||m)) { ans=0; memset(maze,0,sizeof(maze)); memset(en,0,sizeof(en)); for(int i=1;i<=n;i++) { for(int j=1;j<=m;) { char ch; scanf("%c",&ch); if(ch=='#') maze[i][j]=-1,j++; else if(ch=='.'||ch=='@') maze[i][j]=0,j++; if(ch=='@') { sx=i,sy=j-1; } } } scanf("%d",&xx); for(int i=1;i<=xx;i++) { int a,b; scanf("%d%d",&a,&b); G[i].x=a; G[i].y=b; } G[0].x=sx;G[0].y=sy; for(int i=0;i<=xx;i++){ for(int j=0;j<=xx;j++){ dir[i][j]=bfs(G[i].x,G[i].y,G[j].x,G[j].y); } } int ord[100]; for(int i=1;i<=xx;i++){ ord[i]=i; } ord[0]=0; int res=100000000; do { int tmp=0; for(int i=0;i<xx;i++){ tmp+=dir[ord[i]][ord[i+1]]; if(dir[ord[i]][ord[i+1]]==-1) tmp=-1; } res=min(res,tmp); }while(next_permutation(ord+1,ord+xx+1)); printf("%d\n",res); } }