问题: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 }
调用这个函数就可以获得所有分法