欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-03-10 12:09:36
...

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的最大数。

相关标签: 动态规划