數組分割問題

  昨天同窗問我一道關於數組分割的問題——有一個無序、元素個數爲2n的正整數數組,要求:如何能把這個數組分割爲元素個數爲n的兩個數組,並是兩個子數組的和最接近。ios

  假設2n個整數之和爲sum。從2n個整數中找出n個元素的和,有三種可能:大於sum/2,等於sum/2,小於sum/2。能夠考慮小於等於sum/2的狀況。使用動態規劃解決這個問題,其實這是一個NP問題,只能儘可能去接近sum/2這個值。數組

  咱們能夠定義dp[k][s]表明從前k個數中去任意個元素,且k小於等於n,其和爲s是否存在;之因此將選出的數之和放在下標中,而不是做爲dp[k]的值,是由於那種作法不知足動態規劃的前提——最優化原理。優化

  

#include <iostream>
#include <mem.h>
using namespace std;
const int MaxN = 100;
const int maxSum = 100000;
bool dp[MaxN][maxSum];
int A[MaxN];
int main()
{
    int n, k, i, s;
    cin >> n;
    for(i = 1; i <= 2*n; i++)
    {
        cin >> A[i];
    }
    int sum = 0;
    for(i = 1; i <= 2*n; i++)
        sum += A[i];
    memset(dp, false, sizeof(dp));
    dp[0][0] = true;
    for(k = 1; k <= 2*n; k++)
    {
        for(i = min(k, n);i >= 1; i--)
        {
            for(s = 1; s <= sum/2; s++)
            {
                if(s >= A[k] && dp[i-1][s-A[k]])
                    dp[i][s] = true;
            }
        }
    }
    for(s = sum/2; s >= 1 && !dp[n][s]; s--);
    cout << "s1 = " << s << ";" << "s2 = " << sum - s << endl;
    return 0;
}
相關文章
相關標籤/搜索