动态规划——0/1背包

什么是0/1背包?

你有一个容量为V的背包,现在有N件物品,每件物品的体积为Vi,价值为Wi求最大可装入的价值为多少?(这个问题还需要细分,有些题目会要求必须装满背包,有些则不要求将背包装满,两者的区别将会体现在给背包赋初值的情况有所不同,此处不再赘述,详情见下文)。

0/1背包的解题思路

因为0/1背包隶属于动态规划,所以必然要求其转移方程,而转移方程需要定义子状态并确定最后一步的操作。

定义子状态

我们现在有背包容量和装入物品数量这两个限制,因此我们可以使用二维数组来存储子状态,我们命名二维数组为dp[int][int],两个维度分别存放当前背包的容量和放入物品的件数,这样我们就可以知道最后一个状态必然是dp[V][N],翻译一下就是容量为V的背包装入前N个物品时的价值。

最后一步

在得到最大价值的最后一步必然是将最后一件物品装入背包容量为V的背包中,那么意味着在装入最后一件物品之前需要一个体积为(Vmax-V最后一件)的背包来存放之前的物品,此时的物品件数也需要-1,也就是说我需要寻找的子状态是dp[Vmax-V最后一件][N-1],这是把这个物品装入背包的情况。也就是0/1背包中“1”的情况。
同时也有另一种情况,就是当我为了装入最后一件物品为放弃前面的一些物品时,我的价值不升反降,这种情况下还不如不装,这便是“0”的情况。

综上所述

0/1背包就是考虑当背包容量为V时,放入物品i究竟值不值得。
倘若放入,那么当前状态dp[V][i]=dp[V-V~当前物品体积~][i-1~(因为要寻找上一个状态,上一个状态的时候物品数量要减去1)~]+W~i~(因为把当前物品放入了背包中,所以要加上当前物品的价值)
倘若不放入,那么当前状态等同于上一种状态,即背包容量不变,物品数量-1即dp[V][i]=dp[V][i-1];
最后判断那个价值高就选择哪种情况,因此,我们可以写出状态转移方程dp[V][i]=max(dp[V][i-1],dp[V-V~i~][i-1]);

程序主体

读入输出按下不表

 memset(dp,0,sizeof(dp));//最先开始全部赋值为0
    for(int i=1;i<=N;i++){//背包中物品的数量
        for(int j=0;j<=V;j++){//背包容量
            if(j<bone[i].vol){
                dp[i][j]=dp[i-1][j];
            }else{
                int a=dp[i-1][j];
                int b=dp[i-1][j-bone[i].vol]+bone[i].val;
                dp[i][j]=a>b?a:b;
            }
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值