本题是将所有的石头重量之和求出并相除,得出两个相差最小的两个集合,并将石头填入小集合,再然后将总量减去小的部分得出大的部分,然后两者相减得出差值。
class Solution {
public int lastStoneWeightII(int[] stones) {
int sum=0;
for(int dk:stones)
{
sum+=dk;
}
int w=sum/2;
int [] dp=new int [w+1];
for(int i=0;i<stones.length;i++)
{
for(int j=w;j>=stones[i];j--)
{
dp[j]=Math.max(dp[j],dp[j-stones[i]]+stones[i]);
}
}
int kd=sum-dp[w]-dp[w];
return kd;
}
}
该题有点难,由于负数加上正数得出目标值,可推出添加负号的元素的大小。然后看添加进入负数的值是否得能填满,若填满则可以得出方法数量
class Solution {
public int findTargetSumWays(int[] nums, int target) {
int sum=0;
for(int m:nums)
{
sum+=m;
}
int mag=sum-target;
if(mag<0||mag%2!=0)
{
return 0;
}
int nig=mag/2;
int [] dp=new int [nig+1];
dp[0]=1;
for(int i=0;i<nums.length;i++)
{
for(int j=nig;j>=nums[i];j--)
{
dp[j]+=dp[j-nums[i]];
}
}
return dp[nig];
}
}
设置dp数组,dp[i][j]:由于1和0分别计数,所以将dp数组定义为2维。先计数数组中的0和1的个数,然后倒序遍历i和j将集合内的每一个小于m和n的值放入背包中。
class Solution {
public int findMaxForm(String[] strs, int m, int n) {
int [][] dp=new int [m+1][n+1];
dp[0][0]=0;
for(int k=0;k<strs.length;k++ )
{
String mnn=strs[k];
int x=0,y=0;
for(int t=0;t<mnn.length();t++)
{
if(mnn.charAt(t)=='0')
{
x++;
}
else
{
y++;
}
}
for(int i=m;i>=x;i--)
{
for(int j=n;j>=y;j--)
{
dp[i][j]=Math.max(dp[i][j],dp[i-x][j-y]+1);
}
}
}
return dp[m][n];
}
}
总结: 很难想到构成背包的前提。