码迷,mamicode.com
首页 > 其他好文 > 详细

动态规划(二) 0-1背包问题

时间:2019-10-02 22:43:23      阅读:111      评论:0      收藏:0      [点我收藏+]

标签:描述   递推   定义   i++   code   顺序   字典   scan   i+1   

1、多阶段决策问题

(1)物品无限的背包 问题

比较原来的硬币问题发现,只是增加了一个重量属性,从而由原来的无权图变成了带权图,这样问题就变成了求以C为起点(终点任意)的、边权之和最大的路径,相对的

d(s)=max(d(s-v[i])+1)变为d(s)=max(d(s-v[i])+w[i])。

(2)0-1背包问题

状态及其转移类似于回溯法中的解答树,解答树的层数,也就是递归函数中的当前填充位置cur,描述的是即将完成的决策序号,在动态规划中称为阶段。

设d(i,j)表示当前在第i层,背包剩余容量为j时接下来的最大重量和,d(i,j)=max{d(i+1,j),d(i+1,j-v[i])+w[i]},边界是i>n时,d=0。简单来说d(i,j)表示把第i,i+1,,,n个物品撞到容量为

j的背包中的最大总重量。

for(int i=n;i>=1;i--)
    for(int j=0;j<=C;j++)
    {
        d[i][j]=(i==n?0:d[i+1][j]);
        if(j>=v[i]) d[i][j]>?=d[i+1][j-v[i]]+w[i];
}

2、规划方向

还可以对称定义:f(i,j)表示把前i个物品装到容量为j的背包中的最大总重量。

f(i,j)=max{f(i-1,j),f(i-1,j-v[i])+w[i]},最终答案f(n,C)

for(int i=1;i<=n;i++)
    for(int j=0;j<=C;j++)
    {
        f[i][j]=(i==0?0:f[i-1][j]);
        if(j>=v[i]) f[i][j] >?=f[i-1][j-v[i]]+w[i];
}

3、滚动数组

memset(f,0,sizeof(f));
for(int i=1;i<=n;i++)
{
    scanf("%d%d",&v,&w);
    for(int j=C;j>=0;j--) 
        if(j>=v) f[j] >?=f[j-v]+w;
}

在递推法中,如计算顺序很特殊,且计算新状态用到的原状态不多,可以尝试滚动数组。但是会让解的打印方案变得复杂。如要求字典序最小的打印方案,则慎用滚动数组,且规划方向也一般用后i个物品最大重量的规划方向。

动态规划(二) 0-1背包问题

标签:描述   递推   定义   i++   code   顺序   字典   scan   i+1   

原文地址:https://www.cnblogs.com/tuilinengshou/p/11618613.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!