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

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

猜你喜欢

转载自blog.csdn.net/sinat_37517996/article/details/105454823