csp赛前刷题 搜索篇 正整数划分问题

https://www.luogu.com.cn/problem/P2404

蒟蒻献上一道水题,灰常水。题目详见链接。

大意如下:任何一个大于1的正整数n,总可以拆分成若干个小于n的正整数之和。 按字典序输出解。

对于本题而言简单的一个dfs+回溯。

上代码,详见批注

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<string>
 4 using namespace std;
 5 int n, m;
 6 int p[1000] = { 1 };
 7 void sc(int t) {
 8 for (int i = 1; i < t; i++)
 9 cout << p[i] << "+";
10 cout << p[t] << endl;
11 }//输出木有问题的啦
12 void dfs(int a) {//a用来记录数--拆分成的数
13 for (int i = p[a - 1]; i <= m; i++) {//回溯后跳出分支
14 if (i == n) continue;//防止最后一行输出n
15 p[a] = i;m -= i;
16 if (m == 0) sc(a);//当m减完,遍历结束,进入输出
17 else dfs(a + 1);
18 m += i;//回溯
19 }
20 }
21 int main() {
22 cin >> n;//输入木有问题的啦
23 m = n;
24 dfs(1);
25 return 0;
26 }
View Code

本题为《信息学奥赛一本通》例题,书中代码如下:

#include<cstdio>
#include<iostream>
#include<cstdlib>
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 < n)//当前数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 << a[i] << "+";
cout << a[t] << endl;
}
View Code
原文地址:https://www.cnblogs.com/lbxer/p/13784629.html