嘛····TSP问题,模拟退火感觉好复杂。。。于是就各种找状压DP的代码,经过个人修改与综合,现加如下修改注释版本。。。
另,状压DP如果状态太多 可能会MLE```
/*
用 f [ i ] [ S ] 表示当前到达 i 号点,状态为 S 的最短路,
最终我们只需在所有的 f [ i ] [ all ] + map [ i ] [ 1 ] 中找一个最大值即可,
all为全为1的01序列,用0表示没走过,1表示走过
那么比如状态S=111,就可以从1号点110,或2号点101,或3号点011走来,这样转移方程就出来了
f [ i ] [ S ] = m i n ( f [ i ] [ S ] , f [ j ] [ S & ( ~ ( 1 < < i ) ) ] ) ;
*/
#include <stdio.h>
#include <string.h>
#define INF 0x3f3f3f3f
int n;
int mpt[20][20];
int dp[20][1<<15];
int min(int a,int b)
{
return a<b?a:b;
}
void solve()
{
int i,j,k,MAX=1<<n;
//MAX=100……0000(n-1个0)
memset(dp,INF,sizeof(dp));
for(i=0;i<n;i++)
{
dp[i][1<<i]=mpt[0][i];
/*
01
10
100
1000
10000
*/
}
for(j=0;j<MAX;j++)
{
for(i=0;i<n;i++)
{
if((j&(1<<i))==0)
continue; //注意运算符优先级
//当j为1XXXXXXXX时,才继续接下来的循环.
for(k=0;k<n;k++)
{
dp[i][j]=min(dp[i][j],dp[k][j&(~(1<<i))]+mpt[k][i]);
//到i点,状态为j的最短路
//(j&(~(1<<i))表示到达k点,状态为:在当前j状态中,但没有到i的所有状态。
//即到达i点的策略有两种,一种是在j状态(即dp[i][j]),另一种是选到k点,再到i点。
}
}
}
printf("%d\n",dp[0][MAX-1]);
//MAX-1为 111111111即所有点均遍历的状态.
}
int main()
{
int i,j;
while(scanf("%d",&n)!=EOF)
{
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
scanf("%d",&mpt[i][j]);
}
}
solve();
}
return 0;
}