您的位置:首页 > 其它

【第一次状压DP】售货员问题

2014-11-24 12:09 155 查看
嘛····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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: