NYOJ176 整数划分(二)(DP,DFS)

题目:

整数划分(二)

时间限制: 1000 ms  |  内存限制: 65535 KB
难度: 3
描述

把一个正整数m分成n个正整数的和,有多少种分法?

例:把5分成3个正正数的和,有两种分法:

1 1 3

1 2 2

输入
第一行是一个整数T表示共有T组测试数据(T<=50)
每组测试数据都是两个正整数m,n,其中(1<=n<=m<=100),分别表示要拆分的正数和拆分的正整数的个数。
输出
输出拆分的方法的数目。
样例输入
2
5 2
5 3
样例输出
2
2
来源
[张云聪]原创
思路:

动态规划:

先考虑DP的思路,先定义dp[m][n]表示在m个数中划分出n个数,一共的方案数

那么我们先考虑存在一个数为1的情况dp[n-1][m-1]:如果存在一个数为1,那么我们把1放在这m个数的最前面,那么还剩下m-1个数需要划分,这时要划分的值为n-1,因为一个数已经确定那么就得到了

如果被划分的数中不包括1,那么我们就先给这些被划分的数减去1,那么总能保证他们的值大于2。那么就是dp[n-m][m]

所以状态转移方程是:dp[i][j]=dp[i-1][j-1]+dp[i-j][j]


递归:

和上面的动规思路差不多,看看代码就知道了


代码1(dp)

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define mem(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f
#define mod 10000007
#define debug() puts("what the fuck!!!")
#define ll long long
using namespace std;
int main()
{
	int i,j,t;
	int dp[105][105]= {1};
	for(i=1; i<=100; i++)
		for(j=1; j<=i; j++)
			dp[i][j]=dp[i-j][j]+dp[i-1][j-1];
	scanf("%d",&t);
	while(t--)
	{
		int n,k;
		scanf("%d%d",&n,&k);
		printf("%d\n",dp[n][k]);
	}
}
代码2(递归)


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define mem(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f
#define mod 10000007
#define debug() puts("what the fuck!!!")
#define ll long long
using namespace std;
int f(int m,int n)
{
	if(m==n||n==1)  return 1;
	else if(mn)    return f(m-1,n-1)+f(m-n,n);
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int m,n;
		scanf("%d%d",&m,&n);
		printf("%d\n",f(m,n));
	}
	return 0;
}






你可能感兴趣的:(【搜索(DFS/BFS)】,【其他dp】)