LeetCode背包题个人总结

01背包 2d

要求

n 个物品每个weight[i] 重量不一样,对应价值value[i],w 容量的背包。求背包能背下的最大价值。(物品不可重复)

分析

vector<vector< int >> dp;
dp[i] [j] :从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少。

两个角度两个递推式
(1)不放物品 dp[i][j] = dp[i - 1][j]
(2)放物品 dp[i][j] = dp[i - 1][j - weight[i]] + value[i]
求两个值的max。

初始化
(1)dp[i][0] = 0 啥都可以取,但是容量为0,总价值必为0;
(2)dp[0][j] = values[0] 容量足够的话(j >= values[0]),只能取第0个。

代码

01二维背包,先遍历物品或者容量都可以

// weight数组的大小 就是物品个数
for(int i = 1; i < weight.size(); i++) // 遍历物品
{ 
    for(int j = 0; j <= bagweight; j++) // 遍历背包容量
    { 
        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]);
        }
    }
}

01背包 1d

分析

dp[j]:容量为j的背包,所背的物品价值可以最大为dp[j],那么dp[0]就应该是0,因为背包容量为0所背的物品的最大价值就是0。

递推式 dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);

注意!!! 或得 dp[j] ,需要提前获得 dp[j - weight] ,为了保证每个物品只使用一次,物品是倒序遍历。

代码

01一维背包,必须遍历物品再容量 !!!

for(int i = 0; i < weight.size(); i++)  // 遍历物品
{
    for(int j = bagWeight; j >= weight[i]; j--) // 遍历背包容量
    { 
        dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
    }
}

完全背包 1d

要求

n 个物品每个weight[i] 重量不一样,对应价值value[i],w 容量的背包。求背包能背下的最大价值。(物品可重复)

分析

vector<vector< int >> dp;
dp[i] [j] :从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少。
与01背包不同的就是,可以重复,01背包为了避免重复,物品遍历是倒序,因此此处可以重复则正序遍历

代码

在完全背包中,对于一维dp数组来说,其实两个for循环嵌套顺序同样无所谓!

// 先遍历物品,再遍历背包
for(int i = 0; i < weight.size(); i++) // 遍历物品
{ 
    for(int j = weight[i]; j < bagWeight ; j++) // 遍历背包容量
    { 
        dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
    }
}

排列组合问题

要求

一组数据,任意取若干个,使得取到的值满足要求。求方法的个数

分析

组合不强调顺序,(1,5)和(5,1)是同一个组合。
排列强调顺序,(1,5)和(5,1)是两个不同的排列。

因此,数据可否倒序使用(1 2 1,正序应该是从小到大)成为了关键。

如果求组合数就是外层for循环遍历物品,内层for遍历背包。
如果求排列数就是外层for遍历背包,内层for循环遍历物品。

递推式: dp[i] += dp[i - nums[j]];

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值