dp 划分数

第一种:求 把n划分为最大值不超过m的 划分数

1)  若是划分多个整数可以存在相同的:

dp[n][m] 存的是n划分为最大值不超过m的划分个数;

dp[n][m] = dp[n][m-1]+dp[n-m][m];

dp[n][m]表示整数 n 的划分中,每个数不大于 m 的划分数。 则划分数可以分为两种情况:

a.划分中每个数都小于 m,相当于每个数不大于 m- 1, 故划分数为 dp[n][m-1],就这样横着从左到有依次类推,一直加着.

b.划分中有一个数为 m. 那就在 n中减去 m ,剩下的就相当于把 n-m 进行划分, 故划分数为 dp[n-m][m];

2).若是划分多个不同的整数:

dp[n][m] = dp[n][m-1] + dp[n-m][m-1];

dp[n][m] 表示整数n的划分中,每个数不大于m的划分数,则可以分为两种情况

a.划分中每个数都小于 m,相当于每个数不大于 m- 1, 故划分数为 dp[n][m-1],就这样横着从左到有依次类推,一直加着.

b.划分中有一个数为 m.在n中减去m,剩下相当对n-m进行划分,并且每一个数不大于m-1,

故划分数为 dp[n-m][m-1];

第二种:将n划分成k个数的划分法:

dp[n][k] = dp[n-k][k] + dp[n-1][k-1];

第一类: n 份中不包含 1 的分法,为保证每份都 >= 2,可以先拿出 k 个 1 分到每一份,然后再把剩下的 n- k 分成 k 份即可,

分法有: dp[n-k][k];也可这样解释:dp[n-k][k],n-k分为k份,因为这k份都是大于0,让着每一份都加上1,变为dp[n][k];

第二类: n 份中至少有一份为 1 的分法,可以先那出一个 1 作为单独的1份,剩下的 n- 1 再分成 k- 1 份即可,分法有:dp[n-1][k-1]

第三种:把n划分为不超过m份的划分数

设dp[i][j] 为把 j 划分为不超过 i 份的划分数;

 dp[i][j] = dp[i][j-i] + dp[i-1][j]

dp[i][j-i] ,把 j-i 划分为不超过 i 份的 方法数(不够 i 份的用 0 补),让i份,每一份都加上1就转移到了dp[i][j]

而这个 j 划分的 i 份,每一份都是大于0的;

dp[i-1][j] 当 j 划分为i-1份时,再填个0,就变成了i份,就转移到了dp[i][j], 这是后可能会有人问那dp[i-2][j],填两个0,不就变成了i份吗,不就也转移到了dp[i][j]了吗,你想想,当你找dp[i-1][j]时,已经加上了dp[i-2][j] 的 方法数,若你这时再加dp[i-2][j] 中的方法数,不就加重复了吗,这就是dp,就是递推,一直累加;

下面是一道第三种类型的题:

蒜头君特别喜欢数学。今天,蒜头君突发奇想:如果想要把一个正整数 nn 分解成不多于 kk 个正整数相加的形式,那么一共有多少种分解的方式呢?

蒜头君觉得这个问题实在是太难了,于是他想让你帮帮忙。

输入格式

共一行,包含两个整数 n(1 \leq n \leq 300)n(1n300) 和 k(1 \leq k \leq 300)k(1k300),含义如题意所示。

输出格式

一个数字,代表所求的方案数。

样例输入
5 3
样例输出
5

题意:求n划分为不超过k份的划分数;

代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

long long  dp[400][400]; //dp[i][j] 当把j划分成不超过i份的划分数; 
int main()
{
	int i,j;
	int n,m;
	scanf("%d%d",&n,&m);
	memset(dp[0],0,sizeof(dp[0]));
	dp[0][0] = 1;
	for(i = 1;i<=m;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("%lld\n",dp[m][n]);
	return 0;
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值