将一个数组分为两个子数组,使分别的和最接近

Problem

Split an array into two sub-arrays such that the absolute difference of two sums is minimal.

Solution 1: Enumeration

To generate sub-array 1, we either include i’th element or don’t include. In this way we can create a binary tree to DFS.

Solution 2: DP

0-1 背包问题。从前k个数中,取若干个,使其和为<= sum/2的最大数。
即物品价值,重量都是数的值,背包容量为floor(sum/2),要使物品价值和最大。

void printAns(vector<int> &v, int sum){
    int n = v.size(), m = sum / 2;
    int dp[m+1] = {};
    for(int i=1; i<=n; i++){
        for(int j=m; j>=1; j--){
            if(j>=v[i-1]) dp[j] = max(dp[j-v[i-1]]+v[i-1], dp[j]);
        }
    }
    printf("%d %d\n", sum-dp[m], dp[m]);
    return;
}

但只能适用于sum不大的情况,否则dp数组会超内存或超时。

Solution 3: 一个枚举的技巧

对于每个元素选或不选的枚举,可以用0-1串生成所有枚举情况。
有k个数,枚举所有选数情况(共2^k种),用1代表选,用0代表不选,那么所有情况是 000...000 ~ 111...111,共k位

int maxcases = 1 << k; //2^k
for(int case=0; case<maxcases; case++){
    //enumerate from 000...000 to 111...111
    for(int pos=0; pos<k; pos++){
        //check each bit position(0~k-1), if it is 1 then we include it into selection
        if((case>>pos) & 1){
            //include this one
        }
    }
}

以这样的枚举方式,找到和<=sum/2的最大数。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值