昨天同窗問我一道關於數組分割的問題——有一個無序、元素個數爲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; }