整数划分问题

目标:编写递归程序,求正整数的所有不同的划分组合。例如输入6,则输出:

6 = 5+1

6 = 4+2

6 = 4+1+1

6 = 3+3

6 = 3+2+1

6 = 3+1+1+1

6 = 2+2+2

6 = 2+2+1+1

6 = 2+1+1+1+1

6 = 1+1+1+1+1+1

解决方法

从特殊到一般,观察上面6的划分,发现6=5+16=4+26=3+36=2+46=1+5;之后在对15之后)、24之后)、33之后)、42之后)、51之后)进行整数划分,为确保不重不漏,这里划分后的每个数小于等于原来划分首数,如最后5的划分后的数(11111)均小于等于划分首数1,即

n=n-k+k(k=12、……、n-1)然后对k进行划分,划分分后每个数均不大于n-k;划分中含划分,A函数调用A函数,这里不难想到采用递归的做法,

问题归约于1.建立递归子式2.寻找递归出口

这里十分突兀地引入整数划分公式,对整数n进行划分,且划分后的每个数最大值小于等于整数m,划分的方法数记为f(n,m)

1. n=1                 f(1,m)=1;

2. m=1                 f(n,1)=f(n-1,1)=……=f(1,1)=1;

3. n>m                f(n,m)=f(n-m,m)+f(n,m-1)    //这里对m的划分看成两部分,第一部分中划分后存在至少一个值为最大值为m,  第二部分划分后每个值均小于m,即可看成对m-1的划分,类比组合数公式:C(MN) = C(M-1N-1)+C(M-1N)

4. n=m                f(n,m)=f(n,n-1)

5. n<m                f(n,m)=f(n,n)              //这里不直接一步到位到f(n,n-1)为了输出当m=n时的整数划分,而非将m=n直接进入m=n-1

引入整数划分公式 ,递归出口、递归子式都确立,最后建立数组保存划分数即可

 

#include<stdio.h>

static int n1;

void divide(int n,int m,int *a,int i);

void print(int *a,int i);

int main()

{

int n,i,a[100];

while(scanf("%d",&n))

{

n1=n;

divide(n,n-1,a,0);

}

return 0;

}

void divide(int n,int m,int *a,int i)

{

if(n==1) {a[i]=1;print(a,i);return;}

else if(m==1){a[i]=1;i++;divide(n-1,m,a,i);}

else if(m<n){a[i]=m;i++;divide(n-m,m,a,i);divide(n,m-1,a,i-1);}

else if(m==n){a[i]=m;print(a,i);divide(n,n-1,a,i);}

else if(m>n){divide(n,n,a,i);}

}

void print(int *a,int i)

{

printf("%d=%d",n1,a[0]);

for(int j=1;j<=i;j++)

{

printf("+%d",a[j]);

}

printf("\n");

}

 

 

 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值