http://poj.org/problem?id=3311
状压DP裸题 但是因为每个点可以经过多次 所以要先跑一遍floyd
忘了n++ 数组开小调了半小时。。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=0x3f3f3f3f;
const int maxn=20;
const int maxs=3e3+10;
int bit[maxs][maxn],dp[maxs][maxn];
int e[maxn][maxn];
int pre[maxn];
int n;
void init()
{
int i,j;
pre[0]=1;
for(i=1;i<=11;i++){
pre[i]=2*pre[i-1];
}
for(i=0;i<pre[11];i++){
for(j=0;j<11;j++){
if(i&(1<<j)) bit[i][j]=1;
}
}
}
void floyd()
{
int i,j,k;
for(k=0;k<n;k++){
for(i=0;i<n;i++){
for(j=0;j<n;j++){
e[i][j]=min(e[i][j],e[i][k]+e[k][j]);
}
}
}
}
int solve()
{
int res,i,j,k;
memset(dp,0x3f,sizeof(dp));
for(i=0;i<n;i++){
dp[pre[i]][i]=e[0][i];
}
for(i=0;i<pre[n];i++){
for(j=0;j<n;j++){
if(bit[i][j]){
for(k=0;k<n;k++){
if(!bit[i][k]){
dp[i+pre[k]][k]=min(dp[i+pre[k]][k],dp[i][j]+e[j][k]);
}
}
}
}
}
res=N;
for(i=0;i<n;i++){
res=min(res,dp[pre[n]-1][i]+e[i][0]);
}
return res;
}
int main()
{
int i,j;
init();
while(scanf("%d",&n)!=EOF){
if(n==0) break;
n++;
for(i=0;i<n;i++){
for(j=0;j<n;j++){
scanf("%d",&e[i][j]);
}
}
floyd();
printf("%d\n",solve());
}
return 0;
}
/*
2
0 1 1000
1 0 2
1000 2 0
*/