整数划分问题
整数划分问题
将正整数n表示成一系列正整数之和,n=n1+n2+n3+...+nk,其中n1 >=n2 >= n3 >= ... >= nk >= 1,k >= 1。
正整数n的这种表示称为正整数n的划分。正整数n的不同划分数称为正整数n的划分数。
递归法求解:
分析:正整数n,划分的最大加数为m,划分个数记为q(n,m)
①当n < 1 或 m < 1,划分数为0;
②当最大加数m = 1,只有一种情况, q(n,m) = 1;
③当最大加数m >= n,实际上最大加数m不大于n,q(n,m) = q(n,n) ;
④q(n,n) = q(n,n - 1) + 1;
⑤当n > m > 1时,q(n,m) = q(n,m - 1) + q(n - m,m)
可分为两种情况:(1)划分中包含m的情况,也就是1到n中大于或等于m的数即 n - m,q(n - m,m)(2)划分中不包含m的情况,则划分中所有值都比m小,也就是n的 m - 1 划分:q(n,m - 1)
1 public static int divide(int n,int m){ 2 if((n < 1) || (m < 1)) 3 return 0; 4 if((n == 1) || (m == 1)) 5 return 1; 6 if(n < m) 7 return divide(n,n); 8 if(n == m) 9 return divide(n,m -1) + 1; 10 return divide(n,m - 1) + divide(n - m,m); 11 }
动态规划法求解:
利用矩阵数组记录数据,数组的最后一个数即为所求。
1 public static int divideDp(int n, int m){ 2 if (n < 1 || m < 1) 3 return 0; 4 int[][] dp = new int[n + 1][m + 1]; 5 dp[0][0] = 0; 6 for (int i = 1; i <= n; i++){ 7 dp[i][0] = 0; 8 dp[i][1] = 1; 9 } 10 for (int j = 1; j <= m; j++){ 11 dp[0][j] = 0; 12 dp[1][j] = 1; 13 } 14 15 for (int i = 1; i <= n; i++){ 16 for (int j = 1; j <= m; j++){ 17 if (i < j) 18 dp[i][j] = dp[i][i]; 19 else if (i == j) 20 dp[i][j] = dp[i][j - 1] + 1; 21 else 22 dp[i][j] = dp[i][j - 1] + dp[i - j][j]; 23 } 24 } 25 return dp[n][m]; 26 }