OpenJudge 015:复杂的整数划分问题

015:复杂的整数划分问题

总时间限制: 200ms 内存限制: 65536kB

描述
将正整数n 表示成一系列正整数之和,n=n1+n2+…+nk, 其中n1>=n2>=…>=nk>=1 ,k>=1 。
正整数n 的这种表示称为正整数n 的划分。

输入
标准的输入包含若干组测试数据。每组测试数据是一行输入数据,包括两个整数N 和 K。
(0 < N <= 50, 0 < K <= N)

输出
对于每组测试数据,输出以下三行数据:
第一行: N划分成K个正整数之和的划分数目
第二行: N划分成若干个不同正整数之和的划分数目
第三行: N划分成若干个奇正整数之和的划分数目

样例输入

5 2

样例输出

2
3
3

提示
第一行: 4+1, 3+2,
第二行: 5,4+1,3+2
第三行: 5,1+1+3, 1+1+1+1+1+1

一些想法
动规的题典型问法就是多少种,而与具体的种类无关,本体采用记忆性递归以提高效率,根据函数参数的多少,来建立数组,如N分为K个正整数之和,就是将问题转化为在前N个数中找出K个正整数之和为N,因此是一个三维数组,递推关系则是dp[i][j][k]=dp[i-1][j][k]+dp[i][j-i][k-1](选择i,但是题目意思是可以重复使用i,因此下标还是i);而对于第二问是不同整数,则变为二维数组,dp[i][j]=dp[i-1][j]+dp[i-1][j-i](选择i,但是题目意思是可以重复使用i,因此下标还是i);第三问是奇数,则只需要加一个判断条件即可,dp[i][j]=dp[i-1][j]+dp[i][j-i](判断i是否是正奇数i%2!=0),根据递推写出递归即可,要特别注意的是,dp中的初始元素不能为0,因有的元素的值确实为0,故应小于0,如-1。

代码

#include
#include
using namespace std;

const int MAX = 55;
int dp1[MAX][MAX][MAX] = { 0 };
//dp[i][j][k]表示把j分成在前i个数字中选出k个之和的种数

int fun1(int i, int j, int k) {
	if (j == 0 && k == 0)
		return 1;
	if (k == 0)
		return 0;
	if (j == 0)
		return 0;
	if (i == 0)
		return 0;
	if (dp1[i][j][k] != -1)
		return dp1[i][j][k];
	int result = fun1(i - 1, j, k);//不选择i
	if (j >= i)
		result += fun1(i, j - i, k - 1);//选择i,但是i还可以重复使用
	dp1[i][j][k] = result;
	return result;
}

int dp2[MAX][MAX] = { 0 };
int fun2(int i, int j) {
	if (j == 0)
		return 1;
	if (i == 0)
		return 0;
	if (dp2[i][j] != -1)
		return dp2[i][j];
	int result = fun2(i - 1, j);//不选择i
	if (j >= i)
		result += fun2(i - 1, j - i);//此时i不能重复
	dp2[i][j] = result;
	return result;
}

int dp3[MAX][MAX] = { 0 };
int fun3(int i, int j) {
	if (j == 0)
		return 1;
	if (i == 0)
		return 0;
	if (dp3[i][j] != -1)
		return dp3[i][j];
	int result = fun3(i - 1, j);//不选择i
	if (i % 2 && j >= i)//奇数
		result += fun3(i, j - i);//同fun1,i可以再选择
	dp3[i][j] = result;
	return result;
}

int main() {
	int N, K;
	memset(dp1, -1, sizeof(dp1));
	memset(dp2, -1, sizeof(dp2));
	memset(dp3, -1, sizeof(dp3));

	while (cin >> N >> K) {
		cout << fun1(N, N, K) << endl;
		cout << fun2(N, N) << endl;
		cout << fun3(N, N) << endl;
	}
	return 0;
}

你可能感兴趣的:(OpenJudge 015:复杂的整数划分问题)