动态规划-背包问题 V
该算法题是lintcode上的背包问题 V,算法解题思路以及方法是参考九章侯老师的方法去实现的。
相关的题目:
动态规划-背包问题
动态规划-背包问题(二)
动态规划-背包问题(三)
动态规划-Backpack VI
动态规划-背包问题 V
1 描述
给出 n 个物品, 以及一个数组, nums[i] 代表第i个物品的大小, 保证大小均为正数, 正整数 target 表示背包的大小, 找到能填满背包的方案数。
每一个物品只能使用一次
2 样例
2.1 样例1
输入:
nums = [1,2,3,3,7]
target = 7
输出:
2
解释:
结果的集合为:
[7]
[1,3,3]
返回 2
2.2 样例2
输入:
nums = [1,1,1,1]
target = 3
输出:
4
解释:
从 4 个物品中任选 3 个,共 4 种选法
3 算法解题思路以及方法
该算法题类似于动态规划-背包问题,在求解的时候也是按照下面的转换方程去处理。
3.1 解题思路:
3.1.1 确定状态
设f[i][j]表示的是前i个物品是否可以拼出j的重量来
3.1.2 转移方程
可以进一步做空间优化,充分利用之前的计算结果:
3.1.3 初始条件和边界情况
初始条件:
f[0][0] = true 表示前0个物品可以拼出0的重量来
f[0][1],…,f[0][m] = false 表示前0个物品无法拼出其他的重量来
边界条件:
计算的前提条件为:j > a[i - 1]
3.1.4 计算顺序
f[0][0] … f[0][m]
…
f[n][0] … f[n][m]
结果为:前n个物品能拼出的重量f[n][0] … f[n][m]
考虑空间优化就可以只开一个两行的数组。
3.2 算法实现
3.2.1 java实现
public class Solution {
/**
* @param nums: an integer array and all positive numbers
* @param target: An integer
* @return: An integer
*/
public int backPackV(int[] nums, int target) {
// write your code here
int n = nums.length;
int[] f = new int[target + 1];
f[0] = 1;
for (int i = 1; i <= target; i++) {
f[i] = 0;
}
for (int i = 1; i <= n; i++) {
for (int j = target; j >= 0; j--) {
if (j >= nums[i - 1]) {
f[j] += f[j - nums[i - 1]];
}
}
}
return f[target];
}
}
3.2.2 C++实现
class Solution {
public:
/**
* @param nums: an integer array and all positive numbers
* @param target: An integer
* @return: An integer
*/
int backPackV(vector<int> &nums, int target) {
// write your code here
int n = nums.size();
vector<int> f(target + 1, 0);
f[0] = 1;
for (int i = 1; i <= n; i++) {
for (int j = target; j >= 0; j--) {
if (j >= nums[i - 1]) {
f[j] += f[j - nums[i - 1]];
}
}
}
return f[target];
}
};