题目链接:http://poj.org/problem?id=2688
大意:给出一个矩形图,回答从起点出发要经过所有指定点的最短路径长度。如果不能经过所有点就输出-1。
因为指定点的数量不超过10,图的大小不超过20×20,所以可以先bfs预处理构建起点和指定点的邻接矩阵。
然后状压dp就好了。dp[i][j]表示状态i,路径最后一个点为j的最短路径长度。i的每位代表哪些点走了。
(ps:是否能经过所有点特判一下就可以了)
/*--------------------------------------------------------
Author:log
Created Time:2016年04月13日 星期三 20时02分50秒
--------------------------------------------------------*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <map>
using namespace std;
const int maxn=25;
const int inf=0x3f3f3f3f;
struct Node{
int x,y;
int d;
Node(){}
Node(int x,int y,int d):x(x),y(y),d(d){}
}node[maxn];
int grap[maxn][maxn];
bool vis[maxn][maxn];
int edge[maxn][maxn];
int dp[1<<11][11];
Node q[maxn*maxn];
int dx[4]={0,0,-1,1};
int dy[4]={-1,1,0,0};
int w,h;
void bfs(int id,int num){
memset(vis,0,sizeof(vis));
int l=0,r=0;
q[r++]=node[id];
vis[node[id].x][node[id].y]=true;
Node u;
int xt,yt;
int cot=0;
while(l<r){
u=q[l++];
for(int i=0;i<4;i++){
xt=u.x+dx[i];
yt=u.y+dy[i];
if(xt<0||xt>=h||yt<0||yt>=w)continue;
if(vis[xt][yt]||grap[xt][yt]==-2)continue;
if(grap[xt][yt]>0){
edge[id][grap[xt][yt]]=edge[grap[xt][yt]][id]=u.d+1;
cot++;
}
if(cot>=num)return ;
vis[xt][yt]=true;
q[r++]=Node(xt,yt,u.d+1);
}
}
}
int solve(int n){
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)if(i!=j)
if(edge[i][j]==0)return -1;
int state=1<<n;
for(int i=0;i<state;i++){
for(int j=0;j<n;j++)dp[i][j]=inf;
}
dp[1][0]=0;
for(int i=1;i<state;i++){
for(int j=0;j<n;j++){
if(i&(1<<j)==0)continue;
for(int k=0;k<n;k++){
if(i&(1<<k))continue;
dp[i|(1<<k)][k]=min(dp[i|(1<<k)][k],dp[i][j]+edge[j][k]);
}
}
}
int ans=inf;
for(int i=0;i<n;i++){
ans=min(dp[state-1][i],ans);
}
if(ans==inf)return -1;
return ans;
}
int main(){
char c;
int cot;
while(scanf("%d %d",&w,&h)==2&&(w||h)){
cot=0;
for(int i=0;i<h;i++){
getchar();
for(int j=0;j<w;j++){
c=getchar();
switch(c){
case '.':grap[i][j]=-1;break;
case 'o':grap[i][j]=0;node[0]=Node(i,j,0);break;
case '*':grap[i][j]=++cot;node[cot]=Node(i,j,0);break;
default:grap[i][j]=-2;break;
}
}
}
memset(edge,0,sizeof(edge));
for(int i=0;i<cot;i++){
grap[node[i].x][node[i].y]=0;
bfs(i,cot-i);
}
printf("%d\n",solve(cot+1));
}
return 0;
}