/* Name: Integer Partitioning problem copyright:author: DATE:06-04-17 09:02 Description: The integer partitioning problem is one of the classical propositions in the algorithm, and the narration about this problem is explained to the recursive time base
This will all involve. The so-called integer division, refers to a positive integer n written in the following form: N=m1+m2+...+mi;
(of which MI is a positive integer and 1 <= mi <= n), then {m1,m2,..., mi} is a division of N.
If the maximum value in {m1,m2,..., mi} does not exceed M, or Max (m1,m2,..., mi) <=m, it is said to belong to an m partition of N.
Here we remember the number of M division of N is f (n,m);
For example, but when n=4, he has 5 divisions, {4},{3,1},{2,2},{2,1,1},{1,1,1,1};
Note that 4=1+3 and 4=3+1 are considered to be the same division. The problem is to find all the dividing numbers of N, that is, f (n, N).
Here we consider the method of F (n,m);
---------------------------------------------------------------------(i) Recursive method ---------------------------------------------------------------------according to the relationship between N and M, consider the following: (1) when n = 1 o'clock, regardless of the value of M (M &G T
0), only one division is {1};
(2) when m = 1 o'clock, no matter how much the value of N, only one division is N 1,{1, 1, 1, ..., 1}; (3) when n = m, according to whether the partition contains N, can be divided into two cases: (a). In the case of the partition containing N, only one is {n};
When the partition does not contain n, the largest number in the division is certainly smaller than N, that is, all of N (n-1).
So f (n, N) = 1 + f (n, n-1);
(4) When n < m, because there is no negative number in the division, it is equivalent to f (n, N); (5) But n > m, according to whether the division contains the largestValue m, can be divided into two situations: (a). The case of the partition containing M, that is {m, {x1, x2, ..., xi}}, where {x1, x2, ..., xi} and for N-m, may reappear M, therefore (N-M) m division, so the number of this division is F (n-m, M)
;
(b). where m is not included in the division, all values in the division are smaller than m, i.e. N (m-1) and the number is F (n, m-1);
So f (n, m) = f (n-m, M) + f (n, m-1); In this case, we can see that the above conclusions have recursive definition features, where (1) and (2) belong to the regression condition, (3) and (4) are special cases and will be converted to the case (5). The situation (5) is a general case, which belongs to the recursive method, whose essence is to solve the problem by reducing m to achieve the regression condition. The recursive expression is as follows: F (n, m) = 1; (n = 1 or M = 1) f (n, N); (N < m) 1+ F (n, m-1); (n = m) f (n-m, M) + f (n, m-1);
(n > M)--------------------------------------------------------------------- (b) Dynamic programming---------------------------------------------------------------------because the integer partitioning problem satisfies the overlapping characteristics of the optimal substructure and the sub problem, it can
To solve by dynamic programming algorithm.
The Top-down algorithm and the bottom-up dynamic programming algorithm are used respectively, and an optimization algorithm is given.
* * #include <iostream> #include <cmath> using namespace std;
const int N = 40; int f[n][n]; Memo, Record N of M dividing the number int fun_2 (int n, int m); Top-down Memo algorithm for solving integer partitioning problem int fun_3 (int n, int m); From the bottom up of the dynamicProgramming algorithm for solving integer partitioning problem int fun_4 (int n, int m); Optimized bottom-up dynamic programming algorithm for solving integer partitioning problem int Fun (int n, int m);
Recursive method for solving integer partition problem int main () {int n = 12;
For (n=1 n<=20; n++) {for (int i=0; i<=n; i++) {for (int j=0; j<=n; j + +) F[i][j] = 0;
} cout << Fun (n, N) << "";
cout << fun_2 (n, N) << "";
cout << fun_3 (n, N) << "";
cout << fun_4 (n, N) << Endl;
System ("pause");
return 0;
int Fun (int n, int m)//recursive solution to integer partitioning problem {if (n = = 0 | | m = = 0) return 0;
if (n = = 1 | | m = = 1) return 1;
if (n < m) return Fun (n, N);
if (n = = m) return Fun (n, n-1) + 1;
Return Fun (N-m, m) + Fun (n, m-1);
an int fun_2 (int n, int m)/Top down Memo algorithm for solving integer partitioning problem {if (F[n][m] > 0) return f[n][m];
if (n = = 0 | | m = = 0) return 0;
if (n = = 1 | | m = = 1) f[n][m] = 1;
else if (n < m) F[n][m] = fun_2 (n, N); else if (n = = m) f[n][m= Fun_2 (n, n-1) + 1;
else f[n][m] = fun_2 (n-m, m) + fun_2 (n, m-1);
return f[n][m];
int fun_3 (int n, int m)/bottom-up dynamic programming algorithm to solve integer partitioning problem {for (int i=1; i<=m; i++) f[0][i] = 1; for (int j=1; j<=m; j + +)/To achieve a bottom-up, you must ensure that J is in the outer loop, then J<=i<=n loop {for (int i=j; i<=n; i++) {f[i][
J] = F[i-j][j] + f[i][j-1];
} return f[n][m]; int fun_4 (int n, int m)//optimized bottom-up dynamic programming algorithm to solve integer partitioning problem {int Cur[n] = {1};//memo, record the results of the current row//Note the cumulative f[i][j in Algorithm 3] (1<=j&
LT;=M), you can use a one-dimensional array instead of a two-dimensional array for (int j=1; j<=m; J + +) {for (int i=j; i<=n; i++) {Cur[i] + = cur[i-j];
} return Cur[n];
}