問題:M個蘋果分給N個人,沒人最少分一個,共有多少種分法?輸出所有的分法
例如:6個蘋果分給三個人,有“2, 2, 2”,“1, 2, 3”,“1, 1, 4”,三種分法,像“1, 2, 3”,“3, 2, 1”,“2, 3, 1”均屬於同一種分法
解決這個問題的思路可以用動態規划的思想,我們最終要獲得的應該是一個二維數組List<List>的結構,里面的每個數組即表示一種分法。
我們可以利用動態規划的思想,假設f(n,m)表示m個蘋果分給n個人所有的分法,那f(n,m)和f(n,m-1)的關系可以理解為:在f(n,m-1)得到的所有分法基礎上,現在多出來了一個蘋果,多出來的蘋果可以分給n中的任意一個人,比如f(n,m-1)的結果集里有一種分法為“x,y,z”,那么f(n,m)就是在這個分法之上,多出了三種“x+1,y,z”,“x,y+1,z”,“x,y,z+1”的分法。而當n=m時,則返回一個[[1,1,1。。。]]的數組,里面的數組長度為n,表示所有人一人一個。
1 private static List<int[]> getAllWays(int n, int m){ 2 List<int[]> result = new ArrayList<>(); 3 if (n == m){ 4 int[] ints = new int[n]; 5 for (int i = 0; i < ints.length; i++) { 6 ints[i] = 1; 7 } 8 result.add(ints); 9 return result; 10 } 11 12 List<int[]> ways = getAllWays(n, m-1); 13 for (int[] way : ways) { 14 for (int i = 0; i < way.length; i++) { 15 int[] newway = way.clone(); 16 newway[i] = way[i] + 1; 17 Arrays.sort(newway);//這里排序是為了不考慮順序 18 if (!isExist(newway,result)){//排除相同分法 19 result.add(newway); 20 } 21 } 22 } 23 return result; 24 } 25 26 private static boolean isExist(int[] array,List<int[]> list){ 27 boolean isExist = false; 28 for (int[] ints : list) { 29 if (array.length != ints.length) continue; 30 int front = 0; 31 while (front < array.length){ 32 if (array[front] != ints[front]) break; 33 front++; 34 } 35 if (front == ints.length){ 36 isExist = true; 37 break; 38 } 39 } 40 return isExist; 41 }
調用這個函數就可以獲得所有分法