【结论】【状压DP】

来源:互联网 发布:什么是根域名服务器 编辑:程序博客网 时间:2024/06/15 18:35

1、
在n个节点的无向图中选n/2条边,使得点两两配对,并使得所选边权值最小

阶段:每一种已选点组成的集合
状态:s表示已选的点的集合,f[s]表示已选出的点连边后的最小权值。
决策:每条边选或不选
方程:f[sU{u,v}]=min f[s]+w(u,v)

代码:

for(int i=0;i<=s;i++) f[i]=inf;    f[0]=0;    for(int i=0;i<=s;i++)    {        for(u=0;(i>>u)&1;u++);        //找最小的、没选出的点        for(v=u+1;v<nn;v++)        //枚举比u大的点         if(!((i>>v)&1))//如果没选         {            t=i|(1<<u)|(1<<v);            f[t]=min(f[t],f[i]+ma[g[u]][g[v]]);         }    }ans=f[s];

EG:http://blog.csdn.net/y__xv/article/details/51997443

2、
找出简单有向图的哈密顿回路

状态:f[s][i],表示已走过的点的集合为s,最后停下的点为i时,走过边最短距离。
方程:f[s{v}][v]=min(f[s][u]+w(u,v))

for(int j,i=1;i<=s;i++)     for(j=0;j<=n;j++) f[i][j]=1e9;    f[1][0]=0;    int u,v,t;    for(int i=1;i<=s;i++)     for(u=0;u<=n;u++)      if((i>>u)&1)       for(v=0;v<=n;v++)        if(!((i>>v)&1))        {            t=i|(1<<v);            f[t][v]=min(f[t][v],f[i][u]+a[u][v]);        }    int ans=1e9;    for(int i=1;i<=n;i++)    {        ans=min(ans,f[s][i]+a[i][0]);     }

EG:http://blog.csdn.net/y__xv/article/details/51997772

3、
有n个物品,m个容器,每个容器只能装某一个特定的子集,不能多也不能少。每个容器有相应的费用,现在希望把全部物品都装进容器,且使用容器的总费用最少。(m可能非常非常大)

状态:f[s]表示已选物品的集合s所能取得的最小费用
方程:f[s]=min(f[s\t]+w[t])

枚举子集:

for(i=s&(s-1);i;i=s&(i-1))    //从大到小枚举s的所有非空真子集 
0 0
原创粉丝点击