杭州现场赛的题目,虽然大神们都说水,但我感觉还是不错的,还适合我这个水平做。
用bfs求出各个宝物之间的最短距离以及和Dudely之间的距离,然后用dfs枚举Dudely访问各个宝物的顺序,最后比较出距离和的最小值即可。
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<queue> #define INF 2139062143 #define MAXN 105 using namespace std; char grid[MAXN][MAXN]; int flag[MAXN][MAXN],N,M,n,ans,x[5],y[5],dis[5][5]; bool used[10],vis[MAXN][MAXN]; int MM[4][2]= {{1,0},{-1,0},{0,1},{0,-1}}; struct Point { int x,y,step; Point(int a,int b,int c):x(a),y(b),step(c) {} }; void bfs(int xx,int yy) { int cur=flag[xx][yy]; queue<Point> q; memset(vis,0,sizeof(vis)); q.push(Point(xx,yy,0)); vis[xx][yy]=true; while(!q.empty()) { Point u=q.front(); q.pop(); for(int i=0; i<4; ++i) { int ta=u.x+ MM[i][0],tb=u.y+MM[i][1]; if(ta<1||tb<1||ta>N||tb>M) continue; if(vis[ta][tb]||grid[ta][tb]=='#') continue; vis[ta][tb]=true; if(flag[ta][tb]!=-1) dis[cur][flag[ta][tb]]=u.step+1; q.push(Point(ta,tb,u.step+1)); } } } void dfs(int now,int res,int cur) { if(cur==n) ans=min(ans,res); else { for(int i=1; i<=n; ++i) if(!used[i]&&dis[now][i]<INF) { used[i]=true; dfs(i,res+dis[now][i],cur+1); used[i]=false; } } } int main() { while(scanf("%d%d",&N,&M)&&!(!N&&!M)) { memset(flag,-1,sizeof(flag)); memset(grid,0,sizeof(grid)); memset(used,0,sizeof(used)); memset(dis,0x7f,sizeof(dis)); for(int i=1; i<=N; ++i) scanf("%s",grid[i]+1); for(int i=1; i<=N; ++i) for(int j=1; j<=M; ++j) if(grid[i][j]=='@') { x[0]=i; y[0]=j; flag[i][j]=0; break; } scanf("%d",&n); for(int i=1; i<=n; ++i) { scanf("%d%d",&x[i],&y[i]); flag[x[i]][y[i]]=i; } for(int i=0; i<=n; ++i) bfs(x[i],y[i]); ans=INF; dfs(0,0,0); if(ans==INF) printf("-1\n"); else printf("%d\n",ans); } return 0; }