提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
一、购物单问题描述
- 一人手握定量的钱,要去购买物品;
- 物品分主件、附件(每个主件最多有两个附件),若要购买附件的话,则必须够买主件,购买主件不一定需要购买附件;
- 物品有三个参数:价格、重要度、区别物品是主件附件的参数。
输入:
- 输入的第 1 行,为两个正整数M、N,用一个空格隔开; 其中 M表示总钱数, N为可购买的物品的个数;
此处的N不意味着必须购买N个物品,而是代表主件、附件加起来,输入的一共有N种物品。 - 从第 2 行到第 N+1 行,每行输入三个参数。第一个参数为价格,第二个参数为重要度,第三个参数表明其为主件或附件。
第三个参数若为0,则表明其为主件,若不为0,则表明其是参数对应主件的附件。
输出:
- 输出一个正整数,输出可以获得的最大的满意度。
购物单问题与0-1背包问题相似,不过略微复杂一些,因此先来看看0-1背包问题
二、0-1背包问题
背包问题描述:
- 有一个背包可以装物品的总重量为W,现有N个物品,每个物品中w[i],价值v[i],用背包装物品,能装的最大价值是多少?
解题思路:
-
状态转移数组:定义状态转移数组dp[i][j]:前i个物品,背包重量为j,能装下的最大价值
-
dp[i][j] = max(dp[i - 1][j - v[i]] + v[j], dp[i-1][j])
购物单问题与0-1背包问题的不同: -
背包问题中,是否选择物品只取决于其的重量与价值,在购物单问题中,如果对应的主件不存在则不能购买附件
三、如何解决这个不同
-
既然附件的选择较为复杂,不妨从主件入手,当选择某个主件后,最终选择可能存在四种情况:
-
- 仅主件,无附件
-
- 主件,附件1
-
- 主件,附件2
-
- 主件,附件1,附件2
-
图像化想象,用容器存储物品:
主件 | 附件1 | 附件2 |
---|---|---|
1号主件 | 主件1的附件1 | 主件1的附件2 |
2号主件 | 主件2的附件1 | 主件2的附件2 |
··· | ··· | ··· |
每个物品有价格、重要度两个参数,所以会有两张表:价格表、价值表
- 显然需要两个容器,分别设置为
vector<vector<int>> price(N+1, vector<int>(3, 0));
vector<vector<int>> value(N+1, vector<int>(3, 0));
//每个容器大小为N+1,每一个主件占一个位置,容器中所存储的元素为vector<int>
//vector<int>的大小为3,vector<int>中3个元素的初始值均为0,每个元素中再包含附件
- 状态转移数组
//dp[i][j]表示在钱数不超过j的情况下,对前i件产品进行选择,所能获得的最大重要度
dp[i][j] = max(dp[i-1][j-value