划分型动态规划 之 CODE[VS] 1039 数的划分 2001年NOIP全国联赛提高组

/*
dp[i][k] := 将整数i分成k份,分法种数
初始化:
	dp[][] = { 0 }
	dp[i][1] = 1
状态方程:
	dp[i][k] = dp[i-1][k-1] + dp[i-k][k]
	
	思想:(引自byvoid大神的博客:https://www.byvoid.com/blog/noip-allsolutions#.E6.95.B0.E7.9A.84.E5.88.92.E5.88.86)
 
		每种拆分方案中,最小的数为w,按照w的不同,我们可以把拆分方案分成2类:
			w=1,我们把1除去,则剩余部分正好是i-1拆分成k-1部分,一共有dp[i-1,k-1])个;
			w>1,所有的数都>1,我们把所有的数-1,则正好是i-k拆分成k部分,一共有dp[i-k,k]个。
		根据加法原理,得出以上方程。
答案:
	dp[N][K]
*/
 1 #define _CRTDBG_MAP_ALLOC
 2 #include <stdlib.h>
 3 #include <crtdbg.h>
 4 #define _CRT_SECURE_NO_WARNINGS
 5 #define HOME
 6 
 7 #include <iostream>
 8 #include <cstdlib>
 9 #include <cstdio>
10 #include <cstddef>
11 #include <iterator>
12 #include <algorithm>
13 #include <string>
14 #include <locale>
15 #include <cmath>
16 #include <vector>
17 #include <cstring>
18 using namespace std;
19 const int INF = 0x3f3f3f3f;
20 const int MaxN = 210;
21 const int MaxK = 10;
22 
23 
24 int N, K;
25 string numStr;
26 int dp[MaxN][MaxK] = { 0 };
27 
28 void Solve()
29 {
30     for (int i = 1; i <= N; ++i)
31     {
32         // 划分从2开始,因为dp[][1]已经初始化过了,否则值会被0覆盖掉。
33         for (int j = 2; j <= K; ++j)
34         {
35             if (i < j) break;
36             dp[i][j] = dp[i - 1][j - 1] + dp[i - j][j];
37         }
38     }
39     cout << dp[N][K] << endl;
40 }
41 
42 int main() 
43 {
44 #ifdef HOME
45     freopen("in", "r", stdin);
46     //freopen("out", "w", stdout);
47 #endif
48 
49     cin >> N >> K;
50     for (int i = 1; i <= N; ++i)
51     {
52         dp[i][1] = 1;
53     }
54     Solve();
55 
56 #ifdef HOME
57     cerr << "Time elapsed: " << clock() / CLOCKS_PER_SEC << " ms" << endl;
58     _CrtDumpMemoryLeaks();
59     system("pause");
60 #endif
61     return 0;
62 }


 
原文地址:https://www.cnblogs.com/shijianming/p/4964669.html