题目描述

某 乡有n个村庄(1<n<15),有一个售货员,他要到各个村庄去售货,各村庄之间的路程s(0<s<1000)是已知的,且A村 到B村与B村到A村的路大多不同。为了提高效率,他从商店出发到每个村庄一次,然后返回商店所在的村,假设商店所在的村庄为1,他不知道选择什么样的路线 才能使所走的路程最短。请你帮他选择一条最短的路。

输入

村庄数n和各村之间的路程(均是整数)。

输出

最短的路程。

样例输入

3 0 2 1 1 0 2 2 1 0

样例输出

3
 
题解:
F[i][j],j是状压后的数,是1表示经过,0表示不经过,表示从起点到i经过k1,k2,k3(k&j==1)的村庄的最小路程.
然后就是DP方程
F[j][k|(1<<j-1)]=max(F[i][k]+dis[i][j]) 其中(1<<i-1)&j==1  (1<<j-1)&j==0
 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int gi(){
int str=;char ch=getchar();
while(ch>'' || ch<'')ch=getchar();
while(ch>='' && ch<='')str=str*+ch-,ch=getchar();
return str;
}
const int N=;
int n;int dis[N][N];int F[N][<<N];
int main()
{
int x;
n=gi();int pp=(<<n)-,tmp;
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
dis[i][j]=gi();
memset(F,/,sizeof(F));
F[][]=;
for(int k=;k<=pp;k++)
{
for(int i=;i<=n;i++)
{
if(!((<<i-)&k))continue;
for(int j=;j<=n;j++)
{
if(j==i || (<<j-)&k || !dis[i][j])continue;
tmp=F[i][k]+dis[i][j];
if(tmp<F[j][k|(<<j-)])F[j][k|(<<j-)]=tmp;
}
}
}
int ans=;
for(int i=;i<=n;i++)
{
if(dis[i][]==)continue;
if(F[i][pp]+dis[i][]<ans)ans=F[i][pp]+dis[i][];
}
printf("%d",ans);
return ;
}
 
05-11 13:14