题目描述
任何一个大于1的自然数n,总可以拆分成若干个小于n的自然数之和。现在给你一个自然数n,要求你求出n的拆分成一些数字的和。每个拆分后的序列中的数字从小到大排序。然后你需要输出这些序列,其中字典序小的序列需要优先输出。
输入格式
输入:待拆分的自然数n。
输出格式
输出:若干数的加法式子。
输入输出样例
输入 #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
说明/提示
用回溯做。。。。
n≤8
分析:不太常规的回溯题,但理解完题目其实还是很简单的。用深搜枚举每一个位置的数字如果其和达到目标值记录到数组并输出即可。要注意的是题目的输出是有序的(从后面的值开始逐渐增大,类似于组合)。采用函数参数记忆就能解决。
#include <iostream>
#include<math.h>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
int n;
int arr[100] = { 0 };
int used[1000] = { 0 };
void dfs(int dep, int sum, int begin) {//dep为枚举的深度,sum为该次路径的和,begin为每次枚举的起点
if (sum == n) { //和达到了目标值结束
for (int j = 1; j < dep; j++) {
if (arr[j] == 0) //该层为0 即空跳过
continue;
cout << arr[j];
if (j != dep - 1)//输出字符
cout << "+";
}
cout << endl;
return;
}
if (sum > n)return;//如果和超出了目标值,结束
for (int j = begin; j < n; j++) {//类似于组合数,后面输出的编号小于前面的
arr[dep] = j;//枚举每次该位置能填的数
dfs(dep + 1, sum + arr[dep], j);
arr[dep] = 0;//回溯该位置的值
}
}
int main()
{
cin >> n;
dfs(1, 0, 1);//深搜
}