测试用例:数组长度5,[30,60,5,15,30],期待输出:20
决策树+dfs做法:
import java.util.*;
public class Main {
public static int min=Integer.MAX_VALUE;//定义一个全局的min
public static void main(String[] args) {
int[] arr = {30,60,5,15,30}; //期待输出是20
int sum=0;
for(int num:arr)
sum+=num;
selectHelper(0,0,0,sum,arr);
System.out.println(min);
}
//用户1当前的总数,用户2当前的总数,第i个物品,总的sum和,arr数组
//决策树!决策树!决策树!
public static void selectHelper(int user1,int user2,int i,int sum,int[]arr)
{
//边界条件
if(user1==user2)
min=Math.min(min,sum-user1-user2);
if(i>=arr.length)
return;
//做决策
//把第i个物品给用户1
selectHelper(user1+arr[i],user2,i+1,sum,arr);
//把第i个物品给用户2
selectHelper(user1,user2+arr[i],i+1,sum,arr);
//第i个物品谁都不给
selectHelper(user1,user2,i+1,sum,arr);
}
} 最开始的做法,想用dp数组来做,但dp的状态定义其实是错误的,原因在注释中已经说明,留下来备忘。
import java.util.*;
public class Main {
public static void main(String[] args) {
int[] a = {30,60,5,15,30}; //期待输出是20
//int[] a = {30,20,5,20,30};
System.out.println(diff(a));
}
public static int diff(int[]a)
{
int len=a.length;
int sum=0;
for(int i=0;i<len;i++)
sum+=a[i];
int[][]dp=new int[len+1][sum/2+1];
//dp[i][j]定义:前i个物品,能够凑出最接近j的数值
for(int i=0;i<=len;i++)
for(int j=0;j<=sum/2;j++)
dp[i][j]=0;
for(int i=1;i<=len;i++)
for(int j=1;j<=sum/2;j++)
if(j>=a[i-1])
dp[i][j]=Math.max(dp[i-1][j],dp[i-1][j-a[i-1]]+a[i-1]);
else
dp[i][j]=dp[i-1][j];
System.out.println(dp[len][sum/2]);
//我知道这道题错在哪了,测试用例的数值凑巧对了,但是dp转移其实是错误的。因为测试用例的dp[len][sum/2]输出是65
//但实际上需要输出的是60。
//这样的dp转移并不能保证,两个数拿的是一样的。
return sum-2*dp[len][sum/2];
}
}
全部评论
(0) 回帖