LintCode刷题——背包问题 IV(动态规划)
题目描述
给出 n 个物品, 以及一个数组, nums[i]
代表第i
个物品的大小, 保证大小均为正数并且没有重复, 正整数 target
表示背包的大小, 找到能填满背包的方案数。
每一个物品可以使用无数次
样例
样例1
输入: nums = [2,3,6,7] 和 target = 7
输出: 2
解释:
方案有:
[7]
[2, 2, 3]
样例2
输入: nums = [2,3,4,5] 和 target = 7
输出: 3
解释:
方案有:
[2, 5]
[3, 4]
[2, 2, 3]
标签
背包型动态规划 动态规划
空间复杂度:O(target)
AC代码
1 public class Solution { 2 /** 3 * @param nums: an integer array and all positive numbers, no duplicates 4 * @param target: An integer 5 * @return: An integer 6 */ 7 public int backPackIV(int[] nums, int target) { 8 // write your code here 9 int n = nums.length; 10 if (n == 0) { 11 return 0; 12 } 13 14 15 // 滚动数组 16 int[][] dp = new int[2][target + 1]; 17 18 int old = 0; 19 int now = 1; 20 21 // i is things j is capacity 22 for (int i = 0; i <= n; ++i) { 23 old = now; 24 now = 1 - now; 25 for (int j = 0; j <= target; ++j) { 26 if (i == 0 && j== 0) { 27 dp[now][j] = 1; 28 } else { 29 // 判断此时是否超过一种物品 30 if (i > 0) { 31 // 判断当前第i - 1个物品的大小是否大于背包容量 32 if (nums[i - 1] > j) { 33 // 如果大于,就直接等于前i - 1个物品容量为j的方案数 34 dp[now][j] = dp[old][j]; 35 } else { 36 // 此时第i - 1个物品的大小小于背包容量,可以考虑放入0~多个 37 dp[now][j] = dp[old][j]; 38 for (int k = 1; k * nums[i - 1] <= j; k++) { 39 dp[now][j] += dp[old][j - k * nums[i - 1]]; 40 } 41 } 42 } else { 43 // 没有物品,肯定没有方案数填满 > 0的背包 44 dp[now][j] = 0; 45 } 46 } 47 } 48 } 49 50 return dp[now][target]; 51 } 52 }