分析
完全填满背包
F(n,c)这里表示使用n个物品能否将容量为C的背包填满,这里是个布尔值
或者用i-1个物品填满背包(此时不用第i个物品),或者用i-1个物品填满c-w(i)的物品(此时可以用w(i)去填满)
code
记忆化搜索
class Solution {
//memo[i][c]表示使用索引为[0...i]的这些元素,是否可以完全填充一个容量为c的背包
//-1表示未计算,0表示不可以填充,1表示可以填充
private int[][] memo;
public boolean canPartition(int[] nums) {
int sum = 0;
for(int i:nums)
sum+=i;
if(sum%2!=0)
return false;
memo = new int[nums.length][sum/2+1];
for(int i=0;i<nums.length;i++)
Arrays.fill(memo[i],-1);
return tryPartition(nums,nums.length-1,sum/2);
}
//使用nums[0....index],是否可以完全填充一个容量为sum的背包
private boolean tryPartition(int[] nums,int index,int sum){
if(sum==0)
return true;
if(sum<0||index<0)
return false;
if(memo[index][sum]!=-1)
return memo[index][sum]==1;
memo[index][sum] = (tryPartition(nums,index-1,sum)||tryPartition(nums,index-1,sum-nums[index]))?1:0;
return memo[index][sum] == 1;
}
}
动态规划
class Solution {
public boolean canPartition(int[] nums) {
int sum = 0;
for(int i:nums)
sum+=i;
if(sum%2!=0)
return false;
int n = nums.length;
int C = sum/2;
boolean[] memo = new boolean[C+1];
for(int i=0;i<=C;i++)
memo[i]=(nums[0]==i);
for(int i=1;i<n;i++)
for(int j=C;j>=nums[i];j--)
memo[j]=memo[j]||memo[j-nums[i]];
return memo[C];
}