sách gpt4 ai đã đi

【Thuật toán】01 Ba lô

In lại 作者:知者 更新时间:2024-03-13 02:00:32 30 4
mua khóa gpt4 Nike

先看题目

物品不能分隔,必须全部取走或者留下,因此称为01背包
(只有不取和取两种状态)

看第一个样例

我们需要把4个物品装入一个容量为10的背包

我们可以简化问题,从小到大入手分析

weight value 2 1 3 3 4 5 7 9

先考虑物品数量为1的情况:

把前1件物品放入容量为1的背包,此时得到的最大价值是:0
把前1件物品放入容量为2的背包,此时得到的最大价值是:1
把前1件物品放入容量为3的背包,此时得到的最大价值是:1
......
把前1件物品放入容量为10的背包,此时得到的最大价值是:1

把前2件物品放入容量为1的背包,此时得到的最大价值是:0
把前2件物品放入容量为2的背包,此时得到的最大价值是:1
把前2件物品放入容量为3的背包,此时得到的最大价值是:3
把前2件物品放入容量为4的背包,此时得到的最大价值是:3
把前2件物品放入容量为5的背包,此时得到的最大价值是:4
把前2件物品放入容量为6的背包,此时得到的最大价值是:4
......
把前2件物品放入容量为10的背包,此时得到的最大价值是:4

把前3件物品放入容量为1的背包,此时得到的最大价值是:0
把前3件物品放入容量为2的背包,此时得到的最大价值是:1
把前3件物品放入容量为3的背包,此时得到的最大价值是:3
把前3件物品放入容量为4的背包,此时得到的最大价值是:5
把前3件物品放入容量为5的背包,此时得到的最大价值是:5
把前3件物品放入容量为6的背包,此时得到的最大价值是:6
......
把前3件物品放入容量为10的背包,此时得到的最大价值是:9

即:先从物品的数量开始枚举,对i件物品枚举所对应的背包容量j,考虑它的最大价值f[i][j]

for(int i=1;i<=n;i++){//总共有n件物品 for(int j=1;j<=m;j++){//背包的最大容量是m } }

对于一个f[i][j]:

(1)假设我们不选择第i件物品,则f[i][j] = f[i-1][j],相当于把前i-1件物品放入这个容量为j的背包,得到的最大值;

(2)假设我们选择第i件物品,则这个物品剩余的空间就是j-w[i],前一次循环的时候必定会算出这个值来,因此可以让:f[i][j] = f[i-1][j-w[i]] + v[i]

两种选择中,我们保留最优解,避免下标出现负数(即j-w[i]可能为负数)

for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ f[i][j]=f[i-1][j]; if(j>=w[i])f[i][j]=max(f[i][j],f[i-1][j-w[i]]+v[i]); } } printf("%d\n",f[n][m]);

其实这道题还有更多的做法,例如递归,从大到小的做法

上面的做法其实是递推,时间复杂度是O(nm),相比递归好一点,使用这种算法只要保证nm在107以内即可。空间复杂度则是O(n*m)

其实上,f数组是可以压缩成一维数组的

对于一个数f[i][j],实际上是只用到了第i-1行

因此,经过简单的优化,只需要一行即可,把上一行的信息移动下来,删掉所有相关第一维度的东西,看看会变成什么样:

f[j]=f[j-w[i]]; //直接存到下一行中 f[j]=f[j]; f[j]=max(f[j],f[j-w[i]]);

对于一维数组的问题所在:循环的顺序会发生变化,如果继续按照从左到右的顺序进行循环的话,我们会发现,每一个数字都会被后面的数据所引用,因此需要从后往前来递推。这样,后面的值更新的时候不会被第二次使用,更新前面的值都不会被影响到。

反正记住是从后往前就行了

完整版的代码

for(int i=1;i<=n;i++){ for(int j=m;j>=w[i];j--){ //此处写j>=w[i]避免下标产生负数 //相当于if(j>=w[i]) f[j]=max(f[j],f[j-w[i]]+v[i]); f[j]=max(f[j],f[j-w[i]]+v[i]); } }
30 4 0
Bài viết được đề xuất: Redis进阶学习01---基础回顾
Bài viết được đề xuất: 《数据结构修炼手册》----二叉树的顺序结构及实现
Bài viết được đề xuất: oauth2-Github第三方登录案例
Bài viết được đề xuất: SQL注入Fuzzing字典
Giấy chứng nhận ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com