Description:
给定一个数,给定一个特定的数量,要求将这个数划分为特定个数量的部分。
请问:共有多少种划分情况?
Input:
数num,规定划分数量part
Output:
划分总数
Sample Input:
4 3
Sample Output:
4(1+1+2,2+2,1+3,4)
要求:
划分出来的数不能为零,划分数量不能为零。并且,仅顺序不同的划分算作一种划分。
例如:
1+3和3+1算是同一种划分。
思路:
对于这个问题,我们考虑如何使用动态规划递推来做。
首先dp[i][j]代表的是将j划分i,i-1,i-2...1份所对应的总共的划分数量。这里总共对应三种情况:
对于i==j的情况,那么将j正好划分为i份就只对应一种情况也就是全一。剩下的就只要再加上将j划分为i-1,i-2...1份的情况就可以了。也就是:
dp[i][j]=1+dp[i-1][j]。
对于i<j的情况,那么考虑将j正好划分为i份,由于j比i大,所以i份的划分中,每一个划分至少是一,所以我们一定有一个基础划分也就是1,1,1,1,1...1。再将剩余的数字j-i分配到这i个”份“上,我们就得到了将j正好划分为i份的结果。剩下的就只要再加上将j划分为i-1,i-2...1份的情况就可以了。也就是:
dp[i][j]=dp[i-1][j]+dp[i][j-i]。
对于i>j的情况,将j强行分为i份是不可能的,至少i==j时才有得分。所以这种情况其实是等价于第一种情况的。也就是:
dp[i][j]=dp[i-1][j]。
Code:
#include<iostream>
using namespace std;
long long dp[10001][10001];
int num;
int part;
//int M;
void solution() {
dp[0][0] = 1;
for (int i = 1;i <= part;i++) {
for (int j = 0;j <= num;j++) {
if (j > i)
dp[i][j] = dp[i - 1][j] + dp[i][j - i];
else if (j == i)
dp[i][j] = dp[i - 1][j] + 1;
else
dp[i][j] = dp[i - 1][j];
}
}
cout << dp[part][num];
}
int main() {
cin >> num >> part;
solution();
return 0;
}