将整数n分成m份,求划分的种数,注意每份不为空,不考虑顺序。
比如整数4的划分,1 1 2 和 1 2 1 以及2 1 1 为同一种划分。
将整数n分成m份,求划分的种数,注意每份不为空,不考虑顺序。
比如整数4的划分,1 1 2 和 1 2 1 以及2 1 1 为同一种划分。
多组测试样例,每组两个整数。n和m。(6<n<=200,2<=m<=6)
每组测试样例输出一行。输出一个整数表示划分的种数。
7 3
4
7的划分有{1,1,5;1,2,4;1,3,3;2,2,3}
2013年武汉科技大学“蓝桥杯”校内选拔赛
思路1:
搜索,n分成m份,可以看成在中间切m-1次,往下搜,最后一次时统计结果就够了。
ps:这种方法如果n、m 的范围大一点是要TLE的,所以还是要用dp解决。
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<map> #include<cmath> #include<set> #include<stack> #include<algorithm> #define maxn 1005 #define MAXN 1000005 #define eps 1e-6 #define INF 0x3f3f3f3f using namespace std; int n,m,ans; void dfs(int le,int cut,int pre) // 当前的左边位置 还要切几次 上一次的长度 { int i,j; if(cut==1) // 还需要切一次的时候统计 { ans+=max(0,(n-le+1)/2-pre+1); return ; } for(i=pre;le-1+(cut+1)*i<=n;i++) // 切一次等于改变左边的位置 { dfs(le+i,cut-1,i); } } int main() { int i,j,t; while(~scanf("%d%d",&n,&m)) { ans=0; dfs(1,m-1,1); printf("%d\n",ans); } return 0; }
思路2:
dp,dp[i][j]表示 i 分成 j 份时的方法总数。
自己dp太弱了,方程有点难想的。
方程:
dp[i][j]=dp[i-1][j-1]+dp[i-j][j];
意义:dp[i][j] 的第一份有两种情况,
1.第一份为1,那么将这份去掉份数少了1(j少了1),i 同时也少了1,所以这种情况由dp[i-1][j-1]推得。
2.第一份大于1,那么后面的每份都大于1 ,将每份都减去1,则i变为 i-j ,j 不变,所以这种情况由 dp[i-j][j]推得。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <string> #include <map> #include <stack> #include <vector> #include <set> #include <queue> #define maxn 15 #define eps 1e-10 #define INF 0x3f3f3f3f typedef long long ll; using namespace std; int n,m,ans; int dp[205][10]; int main() { int i,j; memset(dp,0,sizeof(dp)); for(i=1;i<=200;i++) { dp[i][1]=1; } for(i=1;i<=200;i++) { for(j=2;j<=i&&j<=6;j++) { dp[i][j]=dp[i-1][j-1]+dp[i-j][j]; } } while(~scanf("%d%d",&n,&m)) { printf("%d\n",dp[n][m]); } return 0; }