hdu3538(最短哈密顿路径+状态压缩)
程序员文章站
2024-03-23 22:49:52
...
终于是到了状压DP图论,初心就是为了解决图论。
题意:
给个图,给出m个限制,a,b b这个点必须出现在a之后。 问从1出发的最短哈密顿路径(从起点出发,经过所有的点一次)
概述:
从本质理解状压DP, DP[state] [ u ] 表示已经走过的状态为state , 且当前的节点处于 u ,那么刷表拓展,找出u节点的下一个合法节点,并且必须满足 state 和 下个节点的关系 ,也就是未经过的关系
思路:
限制条件是 a必须在 b 之前出现,那么开一个数组 bef[b ] = bef[b] | (1 < < a) ,这样b 的所以限制条件,都表示在 befb] 里面 , 用二进制形式呈现, 递推的时候,我们在拓展下个节点 v 的时候,就可以用这样 if( bef[v] == state & bef[v] ) ? 这个语句的意思是 ,bef[v] 存在的位置,state也必须存在,那么就满足了限制条件,再拓展。
代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 25;
int mp[maxn][maxn];
int dp[(1<<22)][maxn];
int bef[maxn];
int main()
{
int n,m;
while(scanf("%d%d",&n,&m) != EOF)
{
memset(bef,0,sizeof(bef));
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
{
scanf("%d",&mp[i][j]);
}
while(m--)
{
int a,b;
scanf("%d%d",&a,&b);
bef[b]|=(1<<a);
}
for(int i=0; i<(1<<n); i++)
for(int j=0; j<n; j++)
dp[i][j] = inf;
dp[1][0] = 0;
for(int state = 1 ; state < (1<<n); state++)
{
for(int i=0; i<n; i++) // 用过的
{
if(!(state & (1<<i)))
continue;
if(dp[state][i] == inf)
continue;
for(int j=0; j<n; j++)
{
if(mp[i][j] == -1 || (state&(1<<j))>0 || bef[j] != (state&bef[j]))
continue;
int nsta = state | (1<<j);
dp[nsta][j] = min(dp[nsta][j], dp[state][i] + mp[i][j]);
}
}
}
int ans = inf;
for(int i=0; i<n; i++)
{
ans = min(ans, dp[(1<<n)-1][i]);
}
if(ans == inf)
{
puts("-1");
}
else
printf("%d\n",ans);
}
return 0;
}
上一篇: 二进制状态压缩