本题主考搜索与回溯
# 自然数的拆分问题
## 题目描述
任何一个大于 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
```
## 提示
数据保证,2<=n<=8
#include<bits/stdc++.h>//懒人的万能头,(ps;某教练们建议别用万能头QwQ)
using namespace std;//我学语文,所以打句号。。。 。。。 。。。
int n,ji[1000];//ji数组用来存当前的答案,因为我只用一个数组,所以要回溯QAQ。
//数据是1~8,所以答案最多有8位,即1+1+1+1+1+1+1+1,(n太小了) 。
void dfs(int sum,int place,int qi){//深搜要什么返回值,void(函数无返回)。
//说用字典序排,所以sum表示当前答案的总和,即ji数组每一位累加的和 。
//place表示当前枚举的数是答案的第几位,将当前枚举的数存进ji[place]中,
//qi是记录当前枚举数的大小,because 字典序,所以下一个数要大于等与qi
//即for循环从qi到n-1(为什么n-1???(第一个数一定是1啊QAQ))。
if(sum==n){//ji数组中和已经够了,输出?启动!!! 。
for(int i=1;i<place-1;i++)//看递归函数(place+1)是只加了1,没存值
//所以此时 ji数组里只有place个数,但输出有格式,下面说。
cout<<ji[i]<<"+";//预处理一下,不输出最后的一个,前面都是数+加号
cout<<ji[place-1]<<endl;//单独输出最后一数+我要换行+......(好吧,没了)
return ;}//结束了当前的递归,(我是void,我return后不接值,接了报错哦)
if(sum>n) return;//sum都大于n了,你还不溜溜溜溜溜溜溜?!结束吧您勒;
for(int i=qi;i<=n-1;i++){//作循环,从qi即>=上一个数(理解万岁QAQ!)
ji[place]=i;//ji(答案)数组存数+1,准备递归。
dfs(sum+i,place+1,i);//递归中sum(总和数组)加枚举的i,下个数存进
//place的下一位,即place+1,下个数从第i个数开始枚举,即qi=i(重复*2)
ji[place]=0;//作回溯,重置ji数组,因为:深搜。所以:一条路到底,不会混淆。
}//循环结束力。
}//深搜结束力(悲)。
int main(){//别告诉我你不会写??!!。
cin>>n;//.............................这是输入QAQAQAQAQAQAQAQAQ。
dfs(0,1,1);//现在,ji里没值,所以sum=0,习惯从数组1开始存,所以place=1,最小
//加数是1,从1开始作答案,所以qi=1。(句号)
return 0;//我结束了,你懂了吗?
}//咳
//懂的扣1,没懂的扣眼珠子(凶)。
//下面完整代码。。。。。。。
/*#include<bits/stdc++.h>
using namespace std;
int n,ji[1000];。
void dfs(int sum,int place,int qi){
if(sum==n){
for(int i=1;i<place-1;i++)
cout<<ji[i]<<"+";
cout<<ji[place-1]<<endl;
return ;}
if(sum>n) return;
for(int i=qi;i<=n-1;i++){
ji[place]=i;
dfs(sum+i,place+1,i);
ji[place]=0;
}
}
int main(){
cin>>n;
dfs(0,1,1);
return 0;
}*/
虽然2<=n<=8;
但我数组开的1000,你电脑好可以试试n=1000哦