问题描述:
将正整数n表示成一系列正整数之和:n=n1+n2+…+nk,其中n1≥n2≥…≥nk≥1,k≥1。正整数n的这种表示称为正整数n的划分。
问题1:
输出整数n的所有可能的划分,如:
输入:6
输出: 5+1;
4+2,4+1+1;
3+3,3+2+1,3+1+1+1;
2+2+2,2+2+1+1,2+1+1+1+1;
1+1+1+1+1+1。
我的思路:这种问题已经遇到过很多了,递归搜索所有可能的情况,同时为了记录下每一步的情况,那么就要用到一个数组mark来存储每一步的数,然后递归同时要传递递归的深度k。还有个问题就是递归下一个数的时候,因为是递减的排列的。所以我们还必须记录下上一个的数,然后下一个数必须小于或者等于上一个数。最后递归函数还有有个参数记录当前的长度,来判断是否能够组成我们想要的长度,不能的话就回溯,继续往下一个数去尝试。OK!
代码:
//整数划分问题
#include <stdio.h>
int mark[10];
int n;
void Divid(int now,int k,int prio)
{
//now记录当前长度,k记录深度,prio记录前一个的值。
int i;
if(now > n) return; //不合适,返回。
if(now == n)
{
for(i = 0; i < k-1; i++)
printf("%d+",mark[i]);
printf("%d\n",mark[i]);
}
else
{
for(i = prio; i > 0; i--)
{
if(i <= prio) //必须必前一个要小
{
mark[k]=i;
now+=i;
Divid(now,k+1,i);
now-=i;
}
}
}
}
int main()
{
scanf("%d",&n);
Divid(0,0,n-1);
return 0;
}
/5/29 14:17
问题2:求正整数n的不同划分个数,将最大数n1不大m的划分记住做q(n,m),叫做n的m划分。
输入:n m
输出:n的m划分的总个数。
我的思路:首先要找出递归的公式来,首先分析几种简单的情况,n==1||m==1可以直接得出结果为1;而当n<m时,可以直接求出q(n,n);当n=m时,因为对于n本身只有一种情况,即n,所有可以直接用1+q(n,n-1)来求。最后当n>m时,可以用q(n,m-1)+q(n-m,m),其中q(n-m,m表示的时当m固定后,求剩下可能的情况。参考下图:
代码:
//求整数划分的个数
#include <stdio.h>
int Divid(int n, int m)
{
if (n == 1 || m == 1) return 1; //必须是或
if (n < m) return Divid(n,n);
if (n == m) return 1 + Divid(n,n-1);
return Divid(n,m-1) + Divid(n-m,m);
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
printf("%d\n",Divid(n,m));
return 0;
}
/5/29 14:35