拆分自然数的几种算法
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
拆分自然数的几种算法
【问题描述】自然数的拆分:任何一个大于1的自然数N,总可以拆分成若干个自然数之和,并且有多种拆分方法。例如自然数5,可以有如下一些拆分方法:
【问题描述】自然数的拆分:任何一个大于1的自然数N,总可以拆分成若干个自然数之和,并且有多种拆分方法。例如自然数5,可以有如下一些拆分方法:
5=1+1+1+1+1
5=1+1+1+2
5=1+2+2
5=1+4
5=2+3
算法一用回溯法来实现
针对所给问题,定义问题的解空间;如本题对5的拆分来说,1<=拆分的数<=5。确定易于搜索的解空间结构;如本题对5的拆分来说,用x[]数组来存储解,每个数组元素的取值范围都是1<=拆分的数<=5,从1开始搜索直到5。搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。如本题对5的拆分来说,为了避免重复,x>=x[j](i>j),如x[]={2,3}满足条件而x[]={3,2}就不满足条件不是可行解即无效。
#include
#include
void splitN(int n,int m);//n是需要拆分的数,m是拆分的进度。
int x[1024]={0},total=0 ;//total用于计数拆分的方法数,x[]用于存储解
void main()
{
int n ;
printf("please input the natural number n:");
scanf("%d",&n);
splitN(n,1);
printf("There are %d ways to split natural number %d. ",total,n);
}
void splitN(int n,int m)
{//n是需要拆分的数,m是拆分的进度
int rest,i,j;
for(i=1;i<=n;i++)
{//从1开始尝试拆分
if(i>=x[m-1])
{//拆分的数大于或等于前一个从而保证不重复
x[m]=i ;//将这个数计入结果中
rest=n-i ;//剩下的数是n-i,如果已经没有剩下的了,并且进度(总的拆分个数)大于
1,说明已经得到一个结果了
if(rest==0&&m>1)
{
total++;
printf("%d\t",total);
for(j=1;j { printf("%d+",x[j]); } printf("%d ",x[m]); printf("\n"); } else { splitN(rest,m+1);//否则将剩下的数进行进度为m+1拆分 } x[m]=0;//取消本次结果,进行下一次拆分。环境恢复,即回溯 } } } 算法二用递归来实现 任何一个大于1的自然数n,总可以拆分成若干个小于n的自然数之和,试求n的所有拆分。 用不完全归纳法 n =2 可拆分成2 =1 +1 n =3 可拆分成3 =1 +2 =1 +1 +1 n =4 可拆分成4 =1 +3 =1 +1 +2 =1 +1 +1 +1 =2 +2 …… n =7 可拆分成7 =1 +6 =1 +1 +5 =1 +1 +1 +4 =1 +1 +1 +1 +3 =1 +1 +1 +1 +1 +2 =1 +1 +1 +1 +1+1+1 =1 +1 +1 +2 +2 =1 +1 +2 +3 =1 +2 +4 =1 +2 +2 +2 =1 +3 +3 =2 +5 =2 +2 +3 =3 +4 用数组a 存储完成n 的一种拆分。从上面不完全归纳法的分析n =7 时,按a[1]分类,有a[1]=1,a[1]= 2,…,a[1]= n/2,共n/2 大类拆分。在每一类拆分时,a[1]= i ,a[2]= n - i ,从k=2,继续拆分从a[k]开始,a[k]能否再拆分取决于a[k]/2 是否大于等于a[k-1]。递归过程的参数t 指向要拆分的数a[k] #include using namespace std; int a[100]={0}; void Split(int t) { int i; for(i = 1; i { cout<< a[i]<<"+"; }