任何一个大于 11 的自然数 n,总可以拆分成若干个小于 n 的自然数之和。现在给你一个自然数 n,要求你求出 n 的拆分成一些数字的和。每个拆分后的序列中的数字从小到大排序。然后你需要输出这些序列,其中字典序小的序列需要优先输出。
输入:待拆分的自然数 n。
输出:若干数的加法式子。
输入 7
输出
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。
dfs递归求解,假设1到n-1每个数都有n个,现在在这n(n-1)个数里选取任意个数字,使这些数字的和为n,因此这n(n-1)个数只有选和不选两种状态,正是dfs的经典应用,得到的结果可能会有重复的
所有可以用sort和set进行排序和去重步骤
- #include
- #include
- #include
- #include
- using namespace std;
- vector<int>a;
- string midd;
- set
h; - int n,t;
-
- void dfs(int mid){
- if(mid==n){ //如果数的累加和等于n就记录该组合
- t++;
- vector<int>b(a); //复制数组a
- sort(b.begin(),b.end()); //排序
- midd.clear();
- for(int i=0;i
size();i++){ //把整数数组转换成字符串,并存入set里去重 - midd+=(b[i]+'0');
- if(i
size()-1) midd+='+'; - }
- h.insert(midd);
- }
-
- for(int i=1;i
- if(mid+i<=n){
- mid+=i;
- a.push_back(i);
- dfs(mid); //每一层都加入i并递归到下一层(选)
- a.pop_back(); //回溯,使得这一层不加入i(不选)
- mid-=i;
- }
- }
- }
-
- int main(){
- cin>>n;
- dfs(0);
- for(auto i:h)
- cout<
-
- return 0;
- }
大佬题解
- #include
- #include
- #include
- using namespace std;
- int a[10001]={1},n;
- int search(int,int);
- int print(int);
- int main()
- {
- cin>>n;
- search(n,1);//将要拆分的数n传递给s
- return 0;
- }
- int search(int s,int t)
- {
- int i;
- for(i=a[t-1];i<=s;i++)
- if(i
//当前数i要大于等于前一位数,且不超过n - {
- a[t]=i;//保存当前拆分的数i
- s-=i;//s减去数i,s的值将继续拆分
- if(s==0)print(t);//当s=0时,拆分结束输出结果
- else search(s,t+1);//当s>0时,继续递归
- s+=i;//回溯:加上拆分的数,以便产生所有可能的拆分
- }
- }
- int print(int t)
- {
- for(int i=1;i<=t-1;i++)//输出一种拆分方案
- cout<"+";
-
-
相关阅读:
Vue模板语法
互融云区块链溯源防伪系统开发,超高并发,全程追溯
docker kafka
Java八大排序算法
js逆向第一课 密码学介绍
C语言每日一题(18)数组匹配
第十九章绘图
我要写整个中文互联网界最牛逼的JVM系列教程 | 「类加载子系统」章节:双亲委派机制的工作原理及演示
ES6深入(Symbol、类、迭代器、Set、Map)(二)
VC6 WIN32,Dialog为主窗口编程
-
原文地址:https://blog.csdn.net/weixin_73066129/article/details/134063342