一、題目概述:有乙個沒有排序,元素個數為2n的正整數陣列。要求把它分割為元素個數為n的兩個陣列,並使兩個子陣列的和最接近。
假設陣列a[1..2n]所有元素的和是sum。模仿動態規劃解0-1揹包問題的策略,令s(k, i)表示前k個元素中任意i個元素的和的集合。顯然:
s(k, 1) =
s(k, k) =
s(k, i) = s(k-1, i) u
按照這個遞推公式來計算,最後找出集合s(2n, n)中與sum/2最接近的那個和,這便是答案。這個演算法的時間複雜度是o(2^n).
因為這個過程中只關注和不大於sum/2的那個子陣列的和。所以集合中重複的和以及大於sum/2的和都是沒有意義的。把這些沒有意義的和剔除掉,剩下的有意義的和的個數最多就是sum/2個。所以,我們不需要記錄s(2n,n)中都有哪些和,只需要從sum/2到1遍歷一次,逐個詢問這個值是不是在s(2n,n)中出現,第乙個出現的值就是答案。我們的程式不需要按照上述遞推公式計算每個集合,只需要為每個集合設乙個標誌陣列,標記sum/2到1這個區間中的哪些值可以被計算出來。關鍵**如下:
#includeusingnamespace
std;
//有乙個沒有排序,元素個數為2n的正整數陣列。要求把它分割為元素個數為n的兩個陣列,並使兩個子陣列的和最接近。
int arr = ;
const
int n=5
;const
int sum = 87;//
模仿動態規劃解0-1揹包問題的策略
intsolve1()
dp(2n,n,sum/2+1)就是題目的解。
*///
初始化 memset(dp,0,sizeof
(dp));
for(i = 1 ; i <= 2*n ; ++i)}}
//因為這為最終答案 dp[2*n][n][sum/2+1];
i=2*n , j=n , s=sum/2+1
;
while(i > 0
)
i--;
}cout
intsolve2()}}
//要求最優解則 空間不能優化,
return dp[n][sum/2+1];}
intsolve3()}}
for(s = sum/2+1 ; s >= 0 ; --s)
//要求最優解則空間不能優化
return0;
}int main(void
)
程式設計之美 陣列分割
問題1 有乙個無序 元素個數為n的正整數陣列,要求 如何能把這個陣列分割為兩個子陣列,子陣列的元素個數不限,並使兩個子陣列之和最接近。解答 int sum 0 for i 0 i0 j 從最大的開始遍歷,是為了防止同乙個數選取多次 for j sum 2 j if dp j break return...
程式設計之美 陣列分割
程式設計之美 陣列分割 和擴充套件 將乙個陣列劃分成兩個子陣列,要求他們的和最接近 1.長度要求相等的情況 2.長度沒有要求的情況 都能用動態規劃解決 include includeusing namespace std void arraysplit1 int a,int n 兩個子陣列長度要求相...
程式設計之美 陣列分割
問題 有乙個沒有排序,有2n個元素的陣列,要求把這個陣列分為兩部分,分別含有n個元素,並使兩個子陣列的和最接近。這裡的程式主要是計算這個和的值。比如陣列 計算後符合的分法是 和算出比較小的就可以了是 110 例如陣列 分開後是 和 思考方法 動態規劃 1 計算出陣列中所有元素的和,並把它除以2,這樣...