当前位置: 首页 > news >正文

东方博宜OJ 1424:自然数的分解 ← DFS

【题目来源】
https://www.luogu.com.cn/problem/P2404
https://oj.czos.cn/p/1424

【题目描述】
给定自然数 n,将其拆分成若干自然数的和。输出所有解,每组解中数字按从小到大排列。相同数字的不同排列算一组解。
如,读入整数 3,分解方案如下:

1+1+1  
1+2

再比如,读入整数 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

【输入格式】
一个整数 n(n≤20);

【输出格式】
n 可以分解的自然数和的方案;

【输入样例】
3

【输出样例】
1 1 1  
1 2

【数据范围】
n≤20

【算法分析】
● 这个 dfs(int sum, int step) 函数设计了‌“分解步骤”‌和“‌枚举加数”‌两个核心操作。
首先,考虑一个数值的拆分问题。比如要拆分整数n,每次枚举一个要减去的数字 i,作为拆分的一部分。枚举时,为了不产生如“1+2”和“2+1”这种仅仅是顺序不同的重复结果,函数使用了一个关键技巧:‌枚举下一个加数时,起点从上一个加数开始‌。这保证了所有加数序列都是非递减的,从而避免重复。
其次,从“剩余数值”的角度去理解递归过程会更直观。函数参数 sum 代表当前的“余额”,而 step 记录当前是第几个加数。每层递归的主要工作是根据规则枚举加数。如果找到一个加数i使余额 sum 恰好减到 0,就输出一组解;否则用新的余额继续递归。

● 这个 dfs(int sum, int step) 函数的思路,本质上是在构建一棵‌“搜索树‌”,每一次选择(即加数 i)都会生成一条新的分支。递归的“深度”对应着拆分出的加法项数,而“回溯”操作(sum+=i)则是在完成一条路径的探索后,撤销上一步的选择,以便在同层尝试其他可能的分支。通过这种方式,函数系统地枚举了所有符合规则的加数组合,最终得到所有拆分方案。

● 下面代码,是“洛谷 P2404:自然数的拆分问题”(https://www.luogu.com.cn/problem/P2404)的代码。将其中的 cout<<a[i]<<"+"; 改为 cout<<a[i]<<" "; 便可适用于本题。

【算法代码一】

#include <bits/stdc++.h>
using namespace std;const int maxn=25;
int a[maxn];void print(int step) {for(int i=1; i<step-1; i++) {cout<<a[i]<<"+";}cout<<a[step-1]<<endl;
}void dfs(int sum, int step, int start) {if(sum==0) {if(step>2) print(step);return;}for(int i=start; i<=sum; i++) {a[step]=i;dfs(sum-i,step+1,i);}
}int main() {int n;cin>>n;dfs(n,1,1);return 0;
}/*
in:
5out:
1+1+1+1+1
1+1+1+2
1+1+3
1+2+2
1+4
2+3
*/


【算法代码二】

#include <bits/stdc++.h>
using namespace std;const int maxn=25;
int a[maxn];
int n;void print(int step) {for(int i=1; i<step; i++) {cout<<a[i]<<"+";}cout<<a[step]<<endl;
}//sum为剩余数值,step为当前拆分的步数
void dfs(int sum, int step) {for(int i=a[step-1]; i<=sum; i++) {if(i<n) {a[step]=i;sum-=i;if(sum==0) print(step);else dfs(sum, step+1);sum+=i;}}
}int main() {a[0]=1;cin>>n;dfs(n,1);return 0;
}/*
in:
7out:
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
*/




【参考文献】
https://blog.csdn.net/hnjzsyjyj/article/details/118736059
https://blog.csdn.net/hnjzsyjyj/article/details/156323183
https://blog.csdn.net/hnjzsyjyj/article/details/156341089
https://blog.csdn.net/weixin_43615816/article/details/115421319
https://www.cnblogs.com/tflsnoi/p/13689306.html
 

http://www.jsqmd.com/news/163834/

相关文章:

  • MATLAB优化建模新选择:YALMIP工具箱深度解析与应用实战
  • 音乐标签管理新纪元:从混乱到专业级整理的完整指南
  • VueMindmap终极指南:5分钟快速构建交互式思维导图
  • notepad--:重新定义你的跨平台文本编辑体验
  • Redis 三大高可用模式:主从、哨兵、集群
  • 如何快速掌握TabPFN:高效表格数据预测的完整指南
  • gprMax电磁波仿真与地质雷达模拟完全指南
  • 告别环境配置难题:PyTorch-CUDA-v2.9镜像让GPU训练更简单
  • 深岩银河存档编辑器:新手完全配置与使用手册
  • 通过Jupyter可视化调试PyTorch-CUDA-v2.9镜像中的模型
  • mrpack-install 项目:从零开始的完整部署指南
  • Venera智能漫画导入:从杂乱文件到井然有序的收藏宝库
  • PlugY插件完整教程:暗黑破坏神2单机功能全面升级指南
  • 西安邮电大学考试宝典:如何用历年试卷轻松拿高分
  • 解锁B站宝藏:这款工具让你随心保存高清视频
  • PyTorch-CUDA-v2.9镜像如何注册模型到Model Registry?
  • 智能设计革命:Adobe Illustrator自动化工作流全面解析
  • macOS百度网盘下载加速技术深度解析与实战指南
  • GDS Decompiler终极指南:快速掌握Godot逆向工程工具
  • m3u8下载神器:让在线视频永久保存不再是难题
  • PyTorch-CUDA-v2.9镜像调用GPU进行Token生成的速度对比
  • Zenodo大文件上传完整教程:5分钟掌握命令行高效上传技巧
  • 麻将数据分析进阶指南:从牌谱记录到段位突破
  • 百度网盘秒传脚本:3分钟掌握文件极速转存技巧
  • DDrawCompat:让经典游戏在现代Windows系统完美运行的兼容性修复方案
  • gprMax电磁仿真平台:从科研到工程的完整解决方案
  • B站视频下载终极方案:从零到精通的完整指南
  • CodeCombat编程学习平台完整教程:从游戏新手到代码高手的终极指南
  • Inter字体终极指南:从入门到精通的10个实用技巧
  • 基于PyTorch-CUDA-v2.9镜像的大模型训练全流程实践