01背包问题定义:给定n种物品和一背包。物品i的重量是wi,其价值是vi,背包的容量是c.问如何选择装入背包中的物品,使得装入背包中的物品的总价值最大?背包的容量有
限,被加入到背包里的物品的重量之和要小于或等于c,其次是每个物品不能分割,要么装入要么不装入。其动态转化方程为:
#include#include #include #include
#include #include #include
其中红色表示在前4件物品中,在背包容量为6的情况下最大价值量为17(分别是6+3+8)。
拓展:leetcode:416. Partition Equal Subset Sum
Given a non-empty array containing only positive integers, find if the array can be partitioned into two subsets such that the sum of elements in both subsets is equal.
Note:
Example 1:
Input: [1, 5, 11, 5] Output: true Explanation: The array can be partitioned as [1, 5, 5] and [11].
Example 2:
Input: [1, 2, 3, 5] Output: false Explanation: The array cannot be partitioned into equal sum subsets.这道题的意思就是在数组中挑任意个元素,使得所挑元素的和与剩下的元素的和相同。
第一种方法:
假设数组的元素的个数是n,利用树的结构来解决,对于数组中的每个元素只有取和不取两种情况,所以可以构建一颗深度为n+1的二叉树(不是真的构造,而是通过递归函数调
用实现),向左代表选择当前物品,向右代表不选择当前物品。在函数调用的过程中,可能会有剪枝操作!!!
第二种方法:
就是利用上述01背包的思想,将背包的容量设置为数组所有元素的和的一半(如果数组的和不是偶数则不可能平分)。在这种情况下,每个物品的总量和价值量是1:1的情况,
一旦背包刚好被装满,就是二维数组的最后一个元素的值等于sum/2。可以知道二维数组的最后一个元素的值是小于或等于sum/2的,如果利用01背包思想求得的最大价值量
都小于sum/2那么这个数组不可能存在一个子序列的和刚好等于sum/2.
源码如下:
class Solution {
public:
bool canPartition(vector& nums) {
int sum = 0;
bool flag;
for (int i = 0; ivalue = nums;
int **f = new int*[m];
for (int i = 0; i < m; i++){
f[i] = new int[n + 1];
memset(f[i], 0, sizeof(int)*(n + 1));
}
for (int i = nums[0]; i <= n; i++){
f[0][i] = value[0];
}
for (int i = 1; i
Leetcode上现实内存超超出限制,一直没找出原因来,求大牛指点!!!!
第三种思想:
将数组中任意个元素的和全部列出来(即任意从1到n个个元素之和),将这和全部存放起来,如果这些和都和sum/2不相等,则不存在这样的非空子序列使得它的和是数组所有
元素和的一半!!!!