nyoj90 整数划分 动态规划与分治解法

原题链接:nyoj90 整数划分

//dp代码
//dp[i][j]表示j划分为i份的次数(也叫做j的i划分) 
//考虑n的m划分为a[0]+a[1]+a[2]+...+a[m]=n即dp[m][n]
//1.如果每个a[i]都大于0,令每个a[i]都减1(共减去m个1),那么a[0]+a[1]+a[2]+...+a[m]=n-m于是就转化为n-m的m划分即dp[m][n-m]
//2.如果存在a[i]=0, 那么可以删除a[i],于是就转化为n的m-1划分即dp[m-1][n]
//于是转移方程式为:dp[i][j] = dp[i][j-i] + dp[i-1][j];
#include <cstdio>
int dp[12][12];
int main(){
	int T;
	int n, i, j;
	scanf("%d", &T);
	while(T --){
		scanf("%d", &n);
		dp[0][0] = 1;
		for(i = 1;i <= n;i ++){
			for(j = 0;j <= n;j ++){
				if(j - i >= 0) 
					dp[i][j] = dp[i - 1][j] + dp[i][j - i];
				else
					dp[i][j] = dp[i - 1][j];
			}
		}
		printf("%d\n", dp[n][n]);
	}
	return 0;
}
//分治算法
#include <stdio.h>
int f(int n, int m) //fun(n, m)代表n的所有划分中,最大加数不大于m的划分个数
{
	if(m == 1)   //最大加数是1时只有一种划分 
		return 1;
	else if(m > n) //如果m>n,则fun(n, m)=fun(n, n) 因为n的划分最大数只能是n
		return f(n, n);
	else if(m == n) //m=n时fun(n, m) = fun(n, m-1) + fun(n, 1) = fun(n, m-1) + 1;
		return f(n, m - 1) + 1; 
	else	// n>m时fun(n, m) = fun(n, m - 1) + fun(n - m, m) 即n的所有划分中,最大加数不大于m的划分个数 等于 最大加数不大于m - 1的划分个数 加上 加数有m的全部划分个数
		return f(n, m - 1) + f(n - m, m); //f(n - m, m)就代表加数有m的全部划分个数,比如fun(6 - 3,3)有6=3+3 6=3+2+1 6=3+1+1+1 三种划分 
}
int main()
{
	int T, n;
	scanf("%d", &T);
	while(T --){
		scanf("%d", &n);
		printf("%d\n", f(n, n));
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值