Day42|动态规划4.1

背包理论基础

每个物品只有两种状态,取或不取,所以可以使用回溯法搜出所有的情况,那么复杂度为O(2^n),这里n表示物品数量。用动态规划进行优化。

二维dp数组01背包

1.dp[i][j]表示从标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少。

(j表示背包最大可以承受的重量,也就是背包容量)

2.确定递推公式

不放物品i:有两个方向推出dp[i][j],即背包容量为j,里面不放物品i的最大价值,此时dp[i][j]就是dp[i - 1][j]。(其实就是当物品i的重量大于背包j的重量时,物品i无法放进背包中,所以背包内的价值依然和前面相同。)

放物品i:由dp[i - 1][j - wight[i]]推出,dp[i - 1][j - wight[i]]为背包容量为j - wight[i]的时候不放物品i的最大价值,(最大价值依然还和上次i-1处一样,没变),那么dp[i - 1][j - weight[i]] + value[i](物品i的价值),就是背包放物品i得到的最大价值(背包里没能放进去当前这一件物品,因此背包价值和上一次一样,但是最终价值=当前这个背包的价值(可能含有前面放进的物品)+当前没能放进去的物品的价值)。所以递归公式:dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);

放或不放这个物品的到的价值进行比较,取其中较大的那个。

3.初始化

首先从dp[i][j]定义出发,如果背包容量j为0的话,即dp[i][0],无论是选取哪些物品,背包价值总和一定为0.

状态转移方程dp[i][j] = max(dp[i - 1][j],dp[i - 1][j - weight[i]] + value[i]);可以看出i是由 i -1推导得出,那么i 为0的时候必须进行初始化。   

dp[0][j],即i为0,存放编号为0的物品的时候,各个容量的背包所能存放的最大价值。

那么很明显当j < weight[0]的时候,dp[0][j]应该是0,因为背包容量比编号0的物品重量还小。

(背包本身价值为0,或者说背包当前的价值,取决于放进去物品的总价值,如果当前物品没放进去,就只受到前面放进去的物品总价值的影响,如果放进去了,就受下标为0到i的所有物品的价值的影响。)       

当j >= weight[0]时,dp[0][j]应该是value[0],因为背包容量足够放下编号为0的物品。

                 

for(int j = 0 ; j < weight[0]; j++){
    dp[0][j] = 0;
}
for(int j = weight[0]; j <= bagweight; j++){
    dp[0][j] = value[0];
}

   由递推公式dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i])可以知道,dp[i][j]是从左上方的数值推导得出来的,那么其他下标是什么数值都可以,因为后面会被覆盖。

统一初始化为0,更方便。

vector<vector<int>>dp(weight.size(),vector<int>(bagweight + 1,0));
for(int j = weight[0]; j <= bagweight; j++){
    dp[0][j] = value[0];
}

               i-1时未放入第i件物品,此时对应的背包容量未j-weight[i],,,,此处应知道,背包容量未j时对应放进的物品为i。在这里我们先考虑前 i - 1件物品放入背包的最优解,再考虑第i件。

能不能放的是前提条件是,背包容量j与物品i的重量weight[i],

背包大小只要是大于等于物品重量,就可以放,但第i件物品要不要放,还要从第i - 1件物品为起点进行考虑。

最终决定要不要放的,才是价值的大小。

        

if(j < weight[i])dp[i][j] = dp[i - 1][j];
else dp[i][j] = max(dp[i - 1][j],dp[i - 1][j - weight[i] + value[i]);
//这里在判断背包大小能够容纳第i件物品后,又比较了不放和放第i件物品的价值大小,取大的为结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值