1. 程式人生 > 實用技巧 >poj3311 Hie with the Pie

poj3311 Hie with the Pie

題目連結:https://vjudge.net/problem/POJ-3311

題意:從0點出發,每個點至少走一次,最後回到0點,求最短長度

相比tsp問題的不同之處是每個點可以走超過一次。這個條件的效果是,假如直接相連的兩點間有一條很長的邊w,可能存在另外一條路,重複走過了某個點,使得兩點距離<w。這樣只要求出兩兩點對之間的最短路即可,由於資料很小,使用floyd,然後就是裸的tsp問題

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;

int d[15][15],f[15][(1<<15)],n,i,j,k,s,u,v;

int main(){
	while (cin>>n){
	  if (n==0) break; n++;
	  memset(d,0x3f,sizeof(d));
	  memset(f,0x3f,sizeof(f));
	  for (i=0;i<n;i++)
	    for (j=0;j<n;j++) cin>>d[i][j];
	  for (k=0;k<n;k++)
	    for (i=0;i<n;i++)
	      for (j=0;j<n;j++)
	        d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
	  f[0][1]=0;
	  for (s=0;s<(1<<n);s++)
	    for (v=0;v<n;v++)
	      if (s&(1<<v)){
	      	for (u=0;u<n;u++)
	      	  if ((u!=v)&&s&(1<<u)) 
	      	    f[v][s]=min(f[v][s],f[u][s^(1<<v)]+d[u][v]);
		  }
	  int ans=1e9;
	  for (i=1;i<n;i++) ans=min(ans,f[i][(1<<n)-1]+d[i][0]);
	  cout<<ans<<endl;
	}
	return 0;
}