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的所有非空真子集