n個數分為兩組,兩組數的個數盡可能相等,差值最小


題目描述:對於有n個數的數組,分為兩組,這兩組的數的個數盡可能相等(不超過1),同時兩組的數之和的差值最小。

這個題目使用類似0-1背包問題,思路:從k個數中選i個數,求所有可能的和,並把這些和放在flag中用true表示。(k,i,flag見代碼)

 1 public static void main(String[] args){
 2         int[] arr = {1 ,  2 ,  3 ,  5 ,  7 ,  8 ,  9};
 3         int n = 7;
 4         int sum = 0;
 5         for(int i:arr){
 6             sum += i;
 7         }
 8         boolean[][] flag = new boolean[n/2+1][sum/2+1];
 9         for(int i=0;i<n/2+1;i++){
10             for(int j=0;j<sum/2+1;j++){
11                 flag[i][j] = false;
12             }
13         }
14         flag[0][0] = true;
15         for(int k = 0;k<n;k++){
16             for(int i=k>n/2?n/2:k;i>=1;i--){
17                 //遍歷s(k,i)
18                 for(int j=0;j<=sum/2;j++){
19                     if(j>=arr[k]&&flag[i-1][j-arr[k]]){
20                         flag[i][j] = true;
21                     }
22                 }
23             }
24         }
25         for(int i = sum/2;i>=0;i++){
26             if(flag[n/2][i]) {
27                 System.out.println(i);
28                 break;
29             }
30         }
31     }

我覺得比較難理解的地方就是flag[i-1]這一行是什么意思:代表從k中取i-1個數,他們的各種和的可能的體現(存在即為true)

最里面一層循環的意思是:從i-1這一行中取各種和 然后加上arr[k]湊成i個數的和,體現在flag[i]里面。

第二層循環的意思是:執行1-i這么多行

最外面一層就是不斷往里面加數。

我測試的例子不多,可能有遺漏的地方,請留言指出來,難以理解的地方也可以留言討論。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM