题目:click
题意:找一条经过n个点回到0点的最小距离的路。
给定的邻接矩阵没有没有确定每两点之间的最短距离,由于每个点都可以重复多次计算,预先用floyd处理出最短路。再状压dp。
#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define inf 0x3f3f3f3f
#define MAX_len 50100*4
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int MAXN=1e7+5;
int n;
int a[15][15];
int dp[15][(1<<12)];
int main()
{
while(~scanf("%d",&n)&&n)
{
int i,j,k;
for(i=0;i<=n;i++)
{
for(j=0;j<=n;j++)
{
scanf("%d",&a[i][j]);
}
}
for(i=0;i<=n;i++)//中转节点
{
for(j=0;j<=n;j++)
{
for(k=0;k<=n;k++)
{
a[j][k]=min(a[j][k],a[j][i]+a[i][k]);
}
}
}
int yyyy=(1<<n+1);
memset(dp,inf,sizeof(dp));
dp[0][(1<<i)]=0;
for(i=1;i<=n;i++)
{
int temp=(1<<0)+(1<<i);
dp[i][(1<<i)]=a[0][i];
}
for(i=0;i<yyyy;i++)
{
for(j=0;j<=n;j++)
{
if((1<<j)&i==0||dp[j][i]==inf)
continue;
for(k=0;k<=n;k++)
{
if(j==k)
continue;
if((1<<k)&i)
{
dp[k][i]=min(a[j][k]+dp[j][i],dp[k][i]);
}
else
{
int temp=(1<<k)|i;
dp[k][temp]=min(dp[k][temp],dp[j][i]+a[j][k]);
}
}
}
}
yyyy--;
printf("%d\n",dp[0][yyyy]);
}
return 0;
}