01背包、完全背包、多重背包

参考(都有些错误):
https://github.com/guanjunjian/Interview-Summary/blob/master/notes/algorithms/%E7%BB%8F%E5%85%B8%E7%AE%97%E6%B3%95/01%E8%83%8C%E5%8C%85.md
https://blog.csdn.net/na_beginning/article/details/62884939

 

#include <iostream>
#include <sstream>
#include <vector>
#include <string>using namespace std;/*
01背包问题 每个物品仅一个
状态转移公式:F[i][j] = F[i - 1][j] 和 F[i - 1][j - W[i]] + V[i] 大的那个值
C背包总重量
W每个物品重量
V每个物品价值
n物品总数
inp具有最大价值时,标记哪个物品在包中
返回最大价值
*/
int packages(int C, vector<int> &W, vector<int> &V, int n, vector<int> &inp)
{vector<vector<int> > F(n, vector<int>(C + 1));//F[i][j]记录背包可用重量为j时,前i个物品的最大价值for (int i = 0; i < n; i++)//初始化表格
    {for (int j = 0; j < F[0].size(); j++)F[i][j] = 0;}for (int j = 1; j < F[0].size(); j++)//初始化第一行F[0][j] = (j < W[0]) ? 0 : V[0];//可用重量j大于物品重量,则装入该物品,加上该物品价值for (int i = 1; i < n; i++){for (int j = 1; j < F[0].size(); j++){if (j < W[i])F[i][j] = F[i - 1][j];//装不下该物品elseF[i][j] = (F[i - 1][j] < F[i - 1][j - W[i]] + V[i]) ? F[i - 1][j - W[i]] + V[i] : F[i - 1][j];//可装下该物品。状态转移方程
        }}int result = F[n - 1][F[0].size() - 1];//最大价值//inp标记哪些物品在包中int j = C;for (int i = n-1; i >0 ; i--)//i不可为0,否则F[i-1]越界
    {if (j>W[i] && F[i][j] == F[i - 1][j - W[i]] + V[i])//注意需要j>W[i]
        {inp[i] = 1;j -= W[i];}}if (F[0][j] > 0)//如果背包还可装下,则包含第一个物品inp[0] = 1;//输出动态规划数组for (int i = 0; i < n; i++){for (int j = 0; j < F[0].size(); j++)cout << F[i][j] << " ";cout << endl;}return result;
}/*
01背包问题 滚动数组优化动态规划的空间
原空间OnC,先空间O2C,但是无法输出有哪些物品在包中
*/
int packages_good(int C, vector<int> &W, vector<int> &V, int n)
{vector<vector<int> > F(2, vector<int>(C + 1));//F[i][j]记录背包可用重量为j时,前i个物品的最大价值for (int i = 0; i < 2; i++)//初始化表格
    {for (int j = 0; j < F[0].size(); j++)F[i][j] = 0;}for (int j = 1; j < F[0].size(); j++)//初始化第一行F[0][j] = (j < W[0]) ? 0 : V[0];//可用重量j大于物品重量,则装入该物品,加上该物品价值int k = 0;for (int i = 1; i < n; i++){k = i & 1;//滚动for (int j = 1; j < F[0].size(); j++){if (j < W[i])F[k][j] = F[k ^ 1][j];//装不下该物品elseF[k][j] = (F[k ^ 1][j] < F[k ^ 1][j - W[i]] + V[i]) ? F[k ^ 1][j - W[i]] + V[i] : F[k ^ 1][j];//可装下该物品
        }}return F[k][F[0].size() - 1];//最大价值
}/*
完全背包 每个物品不限制数量
状态转移公式:F[i][j] = F[i - 1][j] 和 F[i][j - W[i]] + V[i] 大的那个值,标记哪些物品在包中也改变
注意是F[i][j - W[i]] + V[i]
也可优化空间
*/
int packages_full(int C, vector<int> &W, vector<int> &V, int n, vector<int> &inp)
{vector<vector<int> > F(n, vector<int>(C + 1));//F[i][j]记录背包可用重量为j时,前i个物品的最大价值for (int i = 0; i < n; i++)//初始化表格
    {for (int j = 0; j < F[0].size(); j++)F[i][j] = 0;}for (int j = 1; j < F[0].size(); j++)//初始化第一行F[0][j] = (j < W[0]) ? 0 : ((j/W[0])*V[0]);//每个物品不止一个for (int i = 1; i < n; i++){for (int j = 1; j < F[0].size(); j++){if (j < W[i])F[i][j] = F[i - 1][j];//装不下该物品elseF[i][j] = (F[i - 1][j] < F[i][j - W[i]] + V[i]) ? F[i][j - W[i]] + V[i] : F[i - 1][j];//可装下该物品。状态转移方程
        }}int result = F[n - 1][F[0].size() - 1];//最大价值//inp标记哪些物品在包中int j = C;int i = n - 1;while (i){while(j && j > W[i] && F[i][j] == F[i][j - W[i]] + V[i]) //如果包含该物品,则一直循环看包含几个该物品
        {inp[i]++;j -= W[i];}i--;//不包含该物品,则跳到下一个物品
    }//输出动态规划数组for (int i = 0; i < n; i++){for (int j = 0; j < F[0].size(); j++)cout << F[i][j] << " ";cout << endl;}return result;
}/*
多重背包 每个物品有数量限制
*/
int packages_multi(int C, vector<int> &W, vector<int> &V, int n, vector<int> &inp, vector<int> &N)//N会被修改
{vector<vector<int> > F(n, vector<int>(C + 1));//F[i][j]记录背包可用重量为j时,前i个物品的最大价值for (int i = 0; i < n; i++)//初始化表格
    {for (int j = 0; j < F[0].size(); j++)F[i][j] = 0;}for (int j = 1; j < F[0].size(); j++)//初始化第一行,每个物品有对应数量N限制
    {int count = (N[0] > j / W[0]) ? j / W[0] : N[0];//可用空间为j时,可以放多少个当前物品,min{可放入数量,物品数量}F[0][j] = (j < W[0]) ? 0 : (count*V[0]);}for (int i = 1; i < n; i++){for (int j = 1; j < F[0].size(); j++){if (j < W[i])F[i][j] = F[i - 1][j];//装不下该物品else{int count = (N[i] > j / W[i]) ? j / W[i] : N[i];F[i][j] = F[i - 1][j];//不放当前物品for (int k = 1; k <= count; k++)//看放入多少个当前物品可以让F[i][j]最大
                {int tmp = F[i - 1][j - k * W[i]] + k * V[i];//放入k个当前物品if (tmp > F[i][j])F[i][j] = tmp;}}}}int result = F[n - 1][F[0].size() - 1];//最大价值cout << result << endl;//inp标记哪些物品在包中int j = C;int i = n - 1;while (i){while (j && N[i] && j > W[i] && F[i][j] == F[i][j - W[i]] + V[i]) //如果包含该物品,则一直循环看包含几个该物品
        {inp[i]++;j -= W[i];--N[i];}i--;//不包含该物品,则跳到下一个物品
    }//输出动态规划数组for (int i = 0; i < n; i++){for (int j = 0; j < F[0].size(); j++)cout << F[i][j] << " ";cout << endl;}return result;
}int main() {vector<int> W{ 4,5,6,2,2 };vector<int> V{ 6,4,5,3,6 };int C = 9;int n = W.size();vector<int> inp(n, 0);//标记是否在包中cout << "1、01背包最大总价值:" << packages(C, W, V, n, inp) << endl;cout << "在背包中的物品编号: ";for (int i = 0; i < inp.size(); i++){if (inp[i] == 1)cout << i << " ";}cout << endl;cout << "2、01背包滚动数组优化最大总价值,无法输出有哪些物品在背包中:" << packages_good(C, W, V, n) << endl;cout << endl;vector<int> inp1(n, 0);//标记是否在包中cout << "3、完全背包最大总价值:" << packages_full(C, W, V, n, inp1) << endl;cout << "输出在背包中物品: ";for (int i = 0; i < inp1.size(); i++){cout << inp1[i] << " ";}cout << endl;cout << endl;vector<int> N{ 1,2,2,2,4 };//每个物品数量vector<int> inp2(n, 0);//标记是否在包中cout << "4、多重背包最大总价值:" << packages_multi(C, W, V, n, inp2, N) << endl;cout << "输出在背包中物品: ";for (int i = 0; i < inp2.size(); i++){cout << inp2[i] << " ";}cout << endl;return 0;
}

 

转载于:https://www.cnblogs.com/beixiaobei/p/10914211.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/424719.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Breadth-first Search 】515. Find Largest Value in Each Tree Row

输入&#xff1a;一颗二叉树 输出&#xff1a;这棵树每一层的最大值。 分析&#xff1a;和513 题目一样&#xff0c;处理层次问题&#xff0c;使用BFS最直观。使用和513一样的模板&#xff0c;只是记录下该层最大值即可。 分析2&#xff1a;用DFS处理层次遍历的问题&#xff0…

第十四期: 拥有7000多万店铺和10多亿件商品的微店如何打造AI系统?

AI技术对于电商至关重要&#xff0c;但AI的实践门槛很高&#xff0c;对于创业公司尤其如此。那么电商创业公司如何打造AI系统?如何利用AI解决实际问题? 作者&#xff1a;夏剑 AI技术对于电商至关重要&#xff0c;但AI的实践门槛很高&#xff0c;对于创业公司尤其如此。那么电…

【数据结构与算法】【算法思想】位图

位图BitMap 算法 public class BitMap { // Java中char类型占16bit&#xff0c;也即是2个字节private char[] bytes;private int nbits;//nbits 总容量public BitMap(int nbits) {this.nbits nbits;this.bytes new char[nbits/161];}//长度16 k/16 定位某一段 k%16定位段中某…

js 高阶函数之柯里化

博客地址&#xff1a;https://ainyi.com/74 定义 在计算机科学中&#xff0c;柯里化&#xff08;Currying&#xff09;是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数&#xff0c;并且返回接受余下的参数且返回结果的新函数的技术 就是只传递给函数…

【Breadth-first Search 】专题3

529 Minesweeper 输入&#xff1a;一个二维矩阵&#xff0c;一些修改规则。  如果点到一个隐藏的地雷M&#xff0c;把它改为X&#xff0c;游戏结束  如果点到一个E&#xff0c;且其周围8邻接的范围没有地雷&#xff0c;那么应该把8邻接的范围的格子全部翻开为E  如果翻开的…

第十五期:一个用户至少“值”100美元,美国最“贵”数据法案CCPA明年初实行!

还在急于应对欧洲GDPR&#xff08;General Data Protection Regulation&#xff0c;通用数据保护条例&#xff09;&#xff1f;那你就OUT了&#xff01; 作者&#xff1a;文摘菌 大数据文摘出品 作者&#xff1a;刘俊寰 还在急于应对欧洲GDPR(General Data Protection Regul…

【数据结构与算法】【算法思想】【推荐系统】向量空间

背景知识 欧几里得的距离公式 推荐系统方法 应用 如何实现一个简单的音乐推荐系统&#xff1f; 1. 基于相似用户做推荐 找到跟你口味偏好相似的用户&#xff0c;把他们爱听的歌曲推荐给你&#xff1b; 2. 基于相似歌曲做推荐 找出跟你喜爱的歌曲特征相似的歌曲&#x…

第十六期:AWS 瘫痪:DNS 被 DDoS 攻击了 15 个小时

AWS警告客户&#xff0c;分布式攻击严重阻碍网络连接&#xff0c;殃及众多网站和应用软件&#xff0c;云巨头AWS遭到攻击后&#xff0c;今天其部分系统实际上断。网。 作者&#xff1a;佚名来源|2019-10-23 15:17 AWS警告客户&#xff0c;分布式攻击严重阻碍网络连接&#xff…

【Breadth-first Search 】752. Open the Lock

输入&#xff1a;deadends 是指针终止状态列表&#xff0c;target 是希望到达的指针状态&#xff0c;初始化指针状态是0000。 输出&#xff1a;如果指针能够到达target状态&#xff0c;则变化的最少步骤是多少。如果不能到达target状态&#xff0c;返回-1。 分析&#xff1a;指…

Spring Security在标准登录表单中添加一个额外的字段

概述 在本文中&#xff0c;我们将通过向标准登录表单添加额外字段来实现Spring Security的自定义身份验证方案。 我们将重点关注两种不同的方法&#xff0c;以展示框架的多功能性以及我们可以使用它的灵活方式。 我们的第一种方法是一个简单的解决方案&#xff0c;专注于重用现…

【数据结构与算法】【算法思想】【MySQL数据库索引】B+树

B树特点 考虑因素 支持按照区间来查找数据 磁盘 IO 操作 N叉树 树的高度就等于每次查询数据时磁盘 IO 操作的次数 在选择 m 大小的时候&#xff0c;要尽量让每个节点的大小等于一个页的大小。读取一个节点&#xff0c;只需要一次磁盘 IO 操作。&#xff08;分裂成两个节点&am…

第十七期:2019人工智能统计数字和一些重要事实

人工智能(AI)每天在以惊人的速度发展。这项技术在2018年已经取得了巨大的成功&#xff0c;简化医疗保健业的工作流程&#xff0c;降低制造业的间接费用&#xff0c;并减少教育业的行政工作量。现在是2019年&#xff0c;每天似乎都有一家新的AI初创公司冒出来&#xff0c;致力于…

Filter和Listener

javaweb三大组件1. Filter&#xff1a;过滤器 2. Listener&#xff1a;监听器3. servlet Filter&#xff1a;过滤器 1. 概念&#xff1a;* 生活中的过滤器&#xff1a;净水器,空气净化器&#xff0c;土匪、* web中的过滤器&#xff1a;当访问服务器的资源时&#xff0c;过滤器可…

【Breadth-first Search 】934. Shortest Bridge

输入&#xff1a;一个二维数组&#xff0c;每个元素的值为0/1。 规则&#xff1a;所有连在一起的1是一个岛屿&#xff0c;数组中包含2个岛屿。连在一起是指上下左右4个方向。可以将0变为1&#xff0c;将2个岛屿链接在一起。 输出&#xff1a;最小改变多少个0就可以将2个岛屿链接…

[Leetcode][第78题][JAVA][子集][位运算][回溯]

【问题描述】[中等] 【解答思路】 1. 位运算 复杂度 class Solution {List<Integer> t new ArrayList<Integer>();List<List<Integer>> ans new ArrayList<List<Integer>>();public List<List<Integer>> subsets(int[] n…

第十八期:闲鱼上哪些商品抢手?Python分析后告诉你

经常看到有朋友在闲鱼卖些小东西又或是自己擅长的一些技能&#xff0c;都能为他们带来不错的 睡后收入。 作者&#xff1a;星安果 1.目标场景 经常看到有朋友在闲鱼卖些小东西又或是自己擅长的一些技能&#xff0c;都能为他们带来不错的睡后收入。 闲鱼上大量的商品&#xf…

【Breadth-first Search 】785. Is Graph Bipartite?

输入&#xff1a;一个无向图graph。graph[i] 的值是一些节点&#xff0c;表示从i到这些节点有边。图中节点用0到graph.length-1表示。这个图没有指向自己的边&#xff0c;也就是说节点i不会有指向节点i的边。输入中不会有重复的边。 输出&#xff1a;如果这个图是bipartite&…

[Leetcode][第1143题][JAVA][最长公共子序列][LCS][动态规划]

【问题描述】[中等] 【解答思路】 时间复杂度&#xff1a;O(N^2) 空间复杂度&#xff1a;O(N^2) class Solution {public int longestCommonSubsequence(String text1, String text2) {int m text1.length(), n text2.length();int[][] dp new int[m 1][n 1];for (int i …

第十九期:程序员节,女朋友偷偷送了我这个...

10 月 24 日&#xff0c;本是个寻常的日子&#xff0c;但是在新时代的中国&#xff0c;却赋予了它新的意义。 作者&#xff1a;技术栈 10 月 24 日&#xff0c;本是个寻常的日子&#xff0c;但是在新时代的中国&#xff0c;却赋予了它新的意义。 正是广大的程序员们&#xff…

【Breadth-first Search 】103. Binary Tree Zigzag Level Order Traversal

输入&#xff1a;一颗二叉树 输出&#xff1a;这棵树的之字形层次遍历。 规则&#xff1a;之字形层次遍历是指第一层从左到右遍历&#xff0c;第二层从右到左遍历。 分析&#xff1a;这与102的区别就是有从左到右&#xff0c;从右到左遍历的交替过程。我们习惯从左到右遍历。最…