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

来源:互联网 发布:gopro windows 编辑:程序博客网 时间:2024/05/17 18:23

题目:

整数划分(二)

时间限制: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),分别表示要拆分的正数和拆分的正整数的个数。
输出
输出拆分的方法的数目。
样例输入
25 25 3
样例输出
22
来源
[张云聪]原创
思路:

动态规划:

先考虑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 <cstdio>#include <cstring>#include <string>#include <set>#include <iostream>#include <cmath>#include <stack>#include <queue>#include <vector>#include <algorithm>#define mem(a,b) memset(a,b,sizeof(a))#define inf 0x3f3f3f3f#define mod 10000007#define debug() puts("what the fuck!!!")#define ll long longusing 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 <cstdio>#include <cstring>#include <string>#include <set>#include <iostream>#include <cmath>#include <stack>#include <queue>#include <vector>#include <algorithm>#define mem(a,b) memset(a,b,sizeof(a))#define inf 0x3f3f3f3f#define mod 10000007#define debug() puts("what the fuck!!!")#define ll long longusing namespace std;int f(int m,int n){if(m==n||n==1)  return 1;else if(m<n)    return 0;else if(m>n)    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;}






原创粉丝点击