欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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;
}
相关标签: 状态压缩

上一篇: 二进制状态压缩

下一篇: