题目
给定一个正整数,将它进行如下分解:
6
6=1+1+1+1+1+1
6=1+1+1+1+2
6=1+1+1+3
6=1+1+2+2
6=1+1+4
6=1+2+3
6=2+2+2
6=1+5
6=2+4
6=3+3
也就是说将一个正整数分解成比它小的若干个正整数的和,求总共多少种分解方法。
思路
从上面可以看出,对一个整数 num,可以分解为2至num个整数的和,并且分解整数的时候,分解的整数不能减小。
我们用递归来思考问题,整数 num 被分解为 cnt 个整数,先分解出一个整数,那么再将剩下的 num-n 分解为 cnt-1 个整数就好了。
但是问题在于如何分解,在分解为cnt个整数时,第一个分解出来的数,依次从1开始到 mun/cnt,这个从上面的数可以发现,然后下次分解的数需要不小于上次分解的数。
代码
#include <stdio.h>
#include "stack.h" //这里使用了栈的数据结构。
Stack s; //声明栈
//访问栈的数据元素
void print(T data)
{
printf("%d ",data);
}
//num分解为cnt个整数相加
void reslove_to_count(int num,size_t cnt)
{
if(cnt == 1)
{ //当分解到只剩一个数的时候
if(stack_top(&s)<=num)
{
stack_push(&s,num); //入栈
stack_foreach(&s,print); //遍历栈
printf("\n");
stack_pop(&s); //一种方法打印出来以后就出栈一个元素,然后退回到上一步,尝试下一种方法
}
}
else
{//cnt>1
int n=0;//先分解出来的这个n可以取以下的值,剩下num-n分解为cnt-1个整数相加
for(n=1;n<=num/cnt;n++)
{
if(stack_is_empty(&s)||stack_top(&s)<=n) //栈为空或者就入栈,栈非空如果需要入栈的元素小于上次入栈的元素就入栈
{
stack_push(&s,n);
reslove_to_count(num-n,cnt-1); //分解剩下的数
stack_pop(&s); //在递归调用结束后,出栈一个元素,然后尝试下一种方法
}
}
}
}
void reslove(int num)
{//把num进行分解,可以分解为[2,num]个数相加
for(int cnt=num;cnt>=2;cnt--)
{
reslove_to_count(num,cnt);
}
}
int main()
{
int num = 0;
printf("请输入要分解的整数:");
scanf("%d",&num);
stack_init(&s,num);
reslove(num);
return 0;
}