P2404 自然数拆分问题

题目描述

任何一个大于 1 的自然数 n,总可以拆分成若干个小于 n 的自然数之和。现在给你一个自然数 n,要求你求出 n 的拆分成一些数字的和。每个拆分后的序列中的数字从小到大排序。然后你需要输出这些序列,其中字典序小的序列需要优先输出。

输入格式

输入:待拆分的自然数 n。

输出格式

输出:若干数的加法式子。

样例 #1

样例输入 #1

7

样例输出 #1

1+1+1+1+1+1+1
1+1+1+1+1+2
1+1+1+1+3
1+1+1+2+2
1+1+1+4
1+1+2+3
1+1+5
1+2+2+2
1+2+4
1+3+3
1+6
2+2+3
2+5
3+4

提示

数据保证,1 <= n <= 8。

思路

深搜的变形题,只要按照一层一层的顺序挨个深搜枚举,就可以过啦。但是注意要进行一点小小的剪枝,以防超时;另外一个就是要判断当前是否是多个(最少2个)组成的表达式,否则不能输出(就比如一个7)。

如何实现深搜枚举?

暴力深搜,必然是for语句搭配输出语句深层嵌套啦。首先定义函数体,其中函数列表内要有三个变量:n(要求拆的数字,同时做倒计功能),last(标记上个枚举的数字是什么)和step(标记当前枚举到第几个数字,同时做数组下标)。接下来分为两部分:

  • 枚举部分,是从last开始一直到n(应为n比较小,就不必在这里进行优化剪枝)暴力枚举,存入数组中。每存一次就要dfs一次。

  • 在枚举部分前面是判断输出部分。首先判断如果last已经大于n并且n!=0,也就是还没枚举完,立刻return。再接着判断如果n等于0并且step大于1(因为表达式最少两个数字)就输出。

深搜枚举代码实现

void f(int n,int last,int step)
{
    if(last>n&&n!=0)return;
    if(n==0&&step>1)
    {
        for(int i=0;i

AC代码

#include
using namespace std;
const int N=1e6+10;
int n,ans,a[N];
void f(int n,int last,int step)//深搜
{
    if(last>n&&n!=0)return;//剪枝优化
    if(n==0&&step>1)
    {
        for(int i=0;i>n;
    f(n,1,0);
    return 0;
}

后记

没啥后记说了,点个赞吧!

你可能感兴趣的:(算法,深度优先,c++,深度优先,算法)