洛谷 P2404 自然数的拆分问题 回溯dfs法 题解

本文介绍了一种使用回溯算法解决自然数拆分问题的方法,通过深度优先搜索(DFS)来寻找所有可能的数字组合,使得给定的自然数能够被拆分为一系列递增的自然数之和。代码示例使用C++实现,详细展示了如何通过递归调用和状态恢复进行有效的搜索。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述
任何一个大于1的自然数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

说明/提示
用回溯做。。。。

n <= 8

**

这是一道典型的DFS题目,与以往练习的题目不同的是这道题涉及到了“回溯”这一知识点,在不同的深搜之间并不只是简单的重复,而是要使状态回到原来应该有的样子在进行下一次深搜,好了不多BB,AC代码奉上。

**

#include <bits/stdc++.h>
using namespace std;
int m = 0;             //m用来存放指定的数字
int num[10] = {1};     //num用来存放每一次相加的数字,第0位一定是1!!!
//定义输出函数
void output(int a);
//深搜!!
void dfs(int n, int t);

//极其简洁的主函数
int main()
{
	cin>>m;
	search(m,1);
	return 0;
}

//有点耐人寻味的深搜!建议在纸上写出流程图更好理解
void dfs(int n, int t){
	int i = 0;            //i表示每次相加的数字
	for(i = num[t-1] ; i <= n; i++){  //注意一下i的取值哈!!
		if(i < m){
			num[t] = i;   //存放数字
			n -= i;       //存放完了当然是减去相应的值
			if(n == 0) print(t); //已经减完了当然直接输出
			else search(n,t+1);  //继续深搜,t+1代表着要在num中排下一位了
			n += i;    //!!!千万别忘了回溯啊!!!
		}
	}
}

//输出函数!!
void output(int a){
//!!千万注意,这里的i要从1开始,
	for(int i = 1 ; i <= a ; i ++){
		cout<<num[i];
		if(i != a) cout<<"+";
	}
	cout<<endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值