划分型动态规划 之 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 }