整数划分是另外的问题:
题目描述 Description
将整数n分成k份,且每份不能为空,任意两种划分方案不能相同(不考虑顺序)。
例如:n=7,k=3,下面三种划分方案被认为是相同的。
7=1+1+5
7=1+5+1
7=5+1+1
问有多少种不同的分法。
输入描述 Input Description
输入:n,k
(1< =n <= 200,1<= k <= 6)
输出描述 Output Description
输出:一个整数,即不同的分法
样例输入 Sample Input
7 3
样例输出 Sample Output
4
数据范围及提示 Data Size & Hint
四种分法为:
1+1+5;
1+2+4;
1+3+3;
2+2+3;
解决思路:
设 f(n,m) 为整数 n 拆分成 m 个数字的方案数.
那么对于每一个情况一定可以分为以下两种情况,且不重不漏。
1.不选 1 的情况
如果不选择 1,我们把 n 拆分成 m 块的情况,可以等价于将每一块都减去1,然后分为m块,即 f(n-m,m)
2.选 1 的情况
那么就是其中一块肯定有一个 1,然后对n-1分成m-1块,即 f(n-1,m-1)。
所以总递推式为 f(n,m)=f(n-m,m)+f(n-1,m-1)
递归结束的条件是
1.n=0 或 n
代码:
#include<iostream>
using namespace std;
int dfs(int n,int k) //把n整数划分成k份
{
if(n==0||n<k||k==0)return 0; //无法继续划分
if(k==1||n==k)return 1; //只能划分成一项
return dfs(n-1,k-1)+dfs(n-k,k);
}
int main()
{
int n,k; //把n整数划分成k份
cin>>n>>k;
int x=dfs(n,k);
cout<<x<<endl;
return 0;
}
把所有情况输出:
代码:
#include <iostream>
#include <stdio.h>
using namespace std;
#define Max 100
int parts;
//整数n分成k份,不考虑顺序,譬如把3分成2份,1 2 和 2 1 是同一种情况。 统计所有情况
int divideNtoKpart(int n,int k,int start)//n:整数,k:分成k份 start:从start开始分类
{
if (k==1) {
return 1;
}
int sum=0;
for (int i=start; i<=n/k; i++) {
sum = sum + divideNtoKpart(n-i, k-1, i);
}
return sum;
}
//统计情况并输出所有情况
int divideNtoKpartAndPrintAllConditions(int n,int k,int start,int condition[Max],int index)
{ //n:整数,k:分成k份 start:从start开始分类 数组condition[Max]:存储分类的情况 index:数组下标,从0开始
if (k==1) {
condition[index]=n;
for (int m=0; m<parts; m++) {
cout<<condition[m]<<" ";
}
cout<<endl;
return 1;
}
int sum=0;
for (int i = start; i<=n/k; i++) {
condition[index]=i;
sum = sum + divideNtoKpartAndPrintAllConditions(n-i, k-1, i, condition, index+1);
}
return sum;
}
int main(int argc, const char * argv[]) {
// insert code here...
int n=0,k=0;
int conditions[Max];
cout<<"输入整数n"<<endl;
cin>>n;
cout<<"输入份数k"<<endl;
cin>>k;
parts=k;
cout<<divideNtoKpartAndPrintAllConditions(n, k, 1, conditions, 0)<<"种"<<endl;
return 0;
}