整数拆分

题目描述: 整数拆分

整数5可以被拆分为6种不同的式子,如下:
4 + 1
3 + 2
3 + 1 + 1
2 + 2 + 1
2 + 1 + 1 + 1
1 + 1 + 1 + 1 + 1
请问100可以被拆分为多少种不同的式子呢?

解答

用递归和动态规划的思想,用非递增的方式选择用于整数N拆分的每一个数,对每个数都有选择和不选择两种可能。
开始的时候和sum = 0(sum是以前选择的所有数的和,每做出一种选择,都对N-sum这个新数进行拆分), 第一个可供选择的数是1,遍历1~N的每个数,都是一种选择。
如果第一个选择的数是1,然后递归的拆分整数N-1,第一个可供选择的数还是1;
如果第一个选择的数是2,然后递归的拆分整数N-2,第一个可供选择的数是2(非递减的思想保证用于拆分的序列不重复);
……

#include <iostream>
using namespace std;

int n, cnt;

void solve(int sum, int pre)
{
    if(sum==n)
    {
        cnt++;  //拆分成功,计数器加1
        return ;
    }
    for(int i = pre; i<=n-sum; i++)
    {
        solve(sum+i, i);
    }
}
int main()
{
    while(cin>>n){
        cnt = 0;
        solve(0, 1);  //最初的和是0,可供选择的数是1(用于拆分的每个数都至少是1)
        cout<<cnt-1<<endl;  //最终结果减1是为了除去 N(+0)=N 这种拆分方法
    }
    return 0;
}

刚刚看了一下这位大神的博客,学到了如何把各种组合的结果输出,代码和注释如下。

#include <iostream>
using namespace std;

int n, cnt;

int data[100];  //用于存储所有选择的数
int datasize;   //用于指示当前data数组的大小

void solve(int sum, int pre)
{
    if(sum==n)  //当拆分成功的时候将data数组中的数输出
    {
        cnt++;
        if(datasize>1){  //大于1是为了除去N这种拆分结果
            cout<<data[0];
            for(int i = 1; i<datasize; i++)
                cout<<"+"<<data[i];
            cout<<endl;
        }
        return ;
    }
    for(int i = pre; i<=n-sum; i++)
    {
        data[datasize++] = i;  //选择i,将i存入data数组
        solve(sum+i, i);
        datasize --;  //不选择i,将data数组的大小减一,相当于删除i
    }
}
int main()
{
    cout<<"Input: ";
    while(cin>>n){
        cnt = 0;
        solve(0, 1);
        cout<<"Output: "<<cnt-1<<endl;
        cout<<"Input: ";
    }
    return 0;
}

最后的运行结果:
这里写图片描述


增加一点东西,如果要求拆分后的各项不相等,可以考虑按照严格递增的顺序选择新加入的数。

#include <iostream>
using namespace std;

int n, cnt;

int data[100];  //用于存储所有选择的数
int datasize;   //用于指示当前data数组的大小

void solve(int sum, int pre)
{
    if(sum==n)  //当拆分成功的时候将data数组中的数输出
    {
        cnt++;
        if(datasize>1){  //大于1是为了除去N这种拆分结果
            cout<<data[0];
            for(int i = 1; i<datasize; i++)
                cout<<"+"<<data[i];
            cout<<endl;
        }
        return ;
    }
    for(int i = pre+1; i<=n-sum; i++)  //如果要求各数不相等,则按照严格递增的顺序选择(pre+1)
    {
        data[datasize++] = i;  //选择i,将i存入data数组
        solve(sum+i, i);
        datasize --;  //不选择i,将data数组的大小减一,相当于删除i
    }
}
int main()
{
    cout<<"Input: ";
    while(cin>>n){
        cnt = 0;
        solve(0, 0);
        cout<<"Output: "<<cnt-1<<endl;
        cout<<"Input: ";
    }
    return 0;
}

运行结果如下:
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值