众所周知,牛能和牛可乐经常收到小粉丝们送来的礼物,每个礼物有特定的价值,他俩想要尽可能按照自己所得价值来平均分配所有礼物。
那么问题来了,在最优的情况下,他俩手中得到的礼物价值和的最小差值是多少呢?
p.s 礼物都很珍贵,所以不可以拆开算哦
[1,2,3,4]
0
他俩一个人拿1,4 。另一个人拿2,3
[1,3,5]
1
他俩一个人拿1,3.另一个人拿5
单个礼物价值不超过100,礼物个数小于100,所有礼物总价值不超过10000
//方法一:
//这种方法也就是暴力搜索了,先对整个数组进行排序,差值最小,确认数组长度n,
//肯定先从数组末尾开始找,如若数组末尾数大于前n-1项和,则停止搜索,否则加上数组最小的数值,在对其他项相加求和,进行比较
//以此类推:
//文字有些难以理解,举个简单的例子[1,2,3,4,5],第一步:5<1+2+3+4;第二步:5+1<4+3+2;第三步:5+1+2>4+3;最后最小差值
//就为8-7=1;但是这个代码好像比较low,只能通过用例,不能a,哈哈;
class Solution {
public:
/*
*
* @param presentVec int整型vector 每个礼物的价值
* @return int整型
*/
int Sum_Array(vector<int>&presentVec,int a,int b){
int sum=0;
for(int i=a;i<b;i++){
sum+=presentVec[i];
}
return sum;
}
int maxPresent(vector<int>& presentVec) {
// write code here
int n=presentVec.size();
if(presentVec.size()==2)return abs(presentVec[0]-presentVec[1]);
int sumA=0;
int sumB=presentVec[n-1];
sort(presentVec.begin(),presentVec.end());
for(int i=0;i<n-1;i++){
sumA+=presentVec[i];
}
if(sumB>=sumA)return sumB-sumA;
else{
for(int i=0;i<n-1;i++){
sumB+=presentVec[i];
sumA=Sum_Array(presentVec,i+1,n-1);
if(sumB>=sumA)return sumB-sumA;
}
}
}
};
//方法2:这个方法就比较巧妙了,还是借鉴牛客上其他大佬的思路,写出来的,理解了就好,代码挺简单的
//01背包问题,两个分组的值越接近总和一半差值越小,
//将总和一半看作背包的最大容量,每次放入的数字就是每次的体积,最后做差返回即可
class Solution{
public:
int maxPresent(vector<int>& presentVec) {
int sum=0;
for(auto num:presentVec){
sum+=num;
}
int split_sum=sum/2;
vector<int>dp(split_sum+1,0);
for(int i=0;i<presentVec.size();i++){
for(int j=split_sum;j>=presentVec[i];j--){
dp[j]=max(dp[j],dp[j-presentVec[i]]+presentVec[i]);
}
}
return (sum-2*dp[split_sum]);//你仔细品,哈哈
}
}; class Solution {
public:
/**
*
* @param presentVec int整型vector 每个礼物的价值
* @return int整型
*/
int maxPresent(vector<int>& presentVec) {
int s = 0;
for(auto &x: presentVec)
s += x;
int V = s/2, dp[V+1];
memset(dp, 0, sizeof(dp));
for(auto &x: presentVec)
for(int j=V;j>=x;j--)
dp[j] = max(dp[j], dp[j-x]+x);
return abs(s-2*dp[V]);
}
}; # # (5842)# @param presentVec int整型一维数组 每个礼物的价值 # @return int整型 (5843)# class Solution: def maxPresent(self , presentVec ): # write code here s = sum(presentVec) bv = s//2 + 1 dp = [0]*bv for i in range(len(presentVec)): for j in range(bv-1, presentVec[i]-1, -1): dp[j] = max(dp[j], dp[j-presentVec[i]] + presentVec[i]) return s - dp[bv-1] - dp[bv-1]01背包问题,两个分组的值越接近总和一半差值越小,将总和一半看作背包的最大容量,每次放入的数字就是每次的体积,最后做差返回即可
int maxPresent(vector<int>& presentVec) {
int sum = 0,size=presentVec.size();
for(int i=0;i<size;i++)sum+=presentVec[i];
vector<int>dp(sum/2+1,0);
for(int i=0;i<size;i++){
for(int j=sum/2;j>=presentVec[i];j--){
dp[j] = max(dp[j],dp[j-presentVec[i]]+presentVec[i]);
}
}
int res=2*dp[sum/2]-sum;
return res>=0?res:-res;
} import java.util.*;
public class Solution {
/**
*
* @param presentVec int整型一维数组 每个礼物的价值
* @return int整型
*/
public int maxPresent (int[] presentVec) {
// write code here
int n = presentVec.length;
if(n == 0) return 0;
int sum = 0;
for(int i = 0; i < n; i++){
sum += presentVec[i];
}
//简化为背包问题
int v = (sum + 1) / 2;
int[] dp = new int[v+1];
for(int i = 0; i < n; i++){
int p = presentVec[i];
for(int j = v; j >= p; j--){
dp[j] = Math.max(dp[j], dp[j-p]+p);
}
}
int result = 2*dp[v] - sum;
return result >= 0 ? result : -result;
}
}
int maxPresent(vector<int>& presentVec) {
// write code here
int sum = 0;
int n = (int)presentVec.size();
for (int i = 0; i < n; i++) {
sum += presentVec[i];
}
vector<int> dp(sum + 1, -1);
auto dfs = [&](auto&& self, int foo, int idx)->int {
if (dp[foo] != -1) {
return dp[foo];
}
if (idx == n) {
dp[foo] = (int)abs(sum - foo - foo);
return dp[foo];
}
dp[foo] = min(self(self, foo + presentVec[idx], idx + 1),
self(self, foo, idx + 1));
return dp[foo];
};
return dfs(dfs, 0, 0);;
} public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* @param presentVec int整型一维数组 每个礼物的价值
* @return int整型
*/
public int maxPresent (int[] presentVec) {
// write code here
// 这不是背包问题吗?
Arrays.sort(presentVec);
int n = presentVec.length;
int sum=0;
for(int p:presentVec){
sum+=p;
}
int target=sum/2;
//sum是背包,东西不可重复装
//dp[i][j] 表示前 i 个物品 装入 重量为j的背包的最大重量
int [][] dp = new int[n+1][target+1];
for(int i=1;i<=n;++i){
for(int j=1;j<=target;++j){
if(j>=presentVec[i-1]){
dp[i][j] = Math.max(dp[i-1][j],dp[i-1][j-presentVec[i-1]]+presentVec[i-1]);
}else{
dp[i][j] = dp[i-1][j];
}
}
}
return Math.abs(sum-2*dp[n][target]);
}
} import java.util.*;
public class Solution {
/**
*
* @param presentVec int整型一维数组 每个礼物的价值
* @return int整型
* 典型的01背包问题
*/
public int maxPresent (int[] presentVec) {
// write code here
int sum = 0;
int value = 0;
for (int i = 0; i < presentVec.length; i++){
sum = sum+ presentVec[i];
value = sum/2;
}
int[][] dp = new int[presentVec.length+1][value+1];
for (int i = 1; i < presentVec.length+1; i++){
for (int j = 1; j < value + 1; j++){
if (presentVec[i-1] > j){
dp[i][j] = dp[i-1][j];
}else if (presentVec[i-1] == j){
dp[i][j] = Math.max(presentVec[i-1], dp[i-1][j]);
}else{
dp[i][j] = Math.max(dp[i-1][j-presentVec[i-1]]+presentVec[i-1], dp[i-1][j]);
}
}
}
int result = (sum - dp[presentVec.length][value]) - dp[presentVec.length][value];
if (result < 0){
return 0-result;
}else{
return result;
}
}
} 01背包问题。不懂搜一下视频讲解01背包得思路 然后就明白了
import java.util.*;
public class Solution {
/**
*
* @param presentVec int整型一维数组 每个礼物的价值
* @return int整型
*/
public int maxPresent (int[] presentVec) {
// write code here
int n = presentVec.length;
if(n == 0){
return 0;
}
//求礼物总和
int sum = 0;
for(int i = 0; i < n;i++){
sum += presentVec[i];
}
int v = sum / 2;
int[] dp = new int[v+1];
for(int i = 0; i < n;i++){
for(int j = v;j >= presentVec[i];j--){
dp[j] = Math.max(dp[j], dp[j-presentVec[i]]+presentVec[i]);
}
}
int res = 2 * dp[v] - sum;
return res >= 0 ? res : -res;
}
} class Solution: def maxPresent(self , presentVec ): zonghe = sum(presentVec) beibao = zonghe // 2 # 挑出最接近总和一半的数出来,在和另一半做差,就是做小的 dp = [0 for i in range(beibao + 1)] # 一维数组来存放每次一迭代的最优结果 for i in range(len(presentVec)): for j in range(beibao, presentVec[i] - 1, -1): # 有公式知,需要右后向前更新,到presentVec[i]是因为再小就放不下这个数,不会有更大的更新值,保持上一次的值就可以 dp[j] = max(presentVec[i] + dp[j - presentVec[i]], dp[j]) # 0-1背包算法的更新公式,放入当前数值后剩下的体积,再放dp中保存的这个体积能放的最多的数,与更新前比较大小 maxvalue = dp[beibao] # 将dp最后一位,即背包体积能放下的最多的数 return abs(maxvalue - (zonghe - maxvalue)) # 装入背包的和没有装入的差,就是最小值
class Solution: def maxPresent(self , p ): # write code here if len(p) <= 0: return 0 p.sort() pa = sum(p) if len(p) < 2: return p[0] dp = [[0 for i in range(pa+1)] for j in range(len(p))] dp[0][p[0]] = 1 dp[0][0] = 1 f = p[0] for i in range(1,len(p)): for j in range(f+1): dp[i][j] += dp[i-1][j] dp[i][j+p[i]] = dp[i][j+p[i]] + 1 if dp[i-1][j] != 0 else 0 f += p[i] res = dp[-1] m = pa for i in range(pa): if res[i] != 0: m = min(m,abs((pa-i)-i)) return m