一、题目
自然数的拆分问题
题目描述
任何一个大于 1 1 1 的自然数 n n n,总可以拆分成若干个小于 n n n 的自然数之和。现在给你一个自然数 n n n,要求你求出 n 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 2\leq n\le 8 2≤n≤8。
二、题解
- 基本思路:
dfs每次找到一组答案按题目要求输出,接着回溯继续找 - 代码:
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define endl "\n"
#define int long long
#define fi first
#define se second
#define lb lower_bound
#define ub upper_bound
#define repn(i,a,n) for(int i = a; i <= n; i++)
#define rep(i,a,n) for(int i = a; i < n; i++)
typedef pair<int,int> PII;
int n;
bool b[10];
vector<int> v;//保存答案
//参数x分别代表着目前找到的数字之和,y表示从什么位置开始找
//第二个参数保证了答案不重复,并且满足典序小的序列需要优先输出
void dfs(int x,int y){
//找到答案输出即可
if(x>=n){
for(int i=0;i<v.size()-1;i++)
cout<<v[i]<<'+';
//cout<<endl;
cout<<v[v.size()-1]<<endl;
return;
}
for(int i=y;i<n;i++){
if(x+i<=n){
v.push_back(i);
dfs(x+i,i);
v.pop_back();
}
}
}
void solve(){
cin>>n;
dfs(0,1);
}
signed main(){
IOS;
int T=1;
while(T--){
solve();
}
return 0;
}