一个整数N(N > 1)可以拆分成若干个大于等于1的自然数之和,请你输出所有不重复的拆分方式。
若满足集合A=B,则称这两种拆分方式是重复的。
例如 6 = 3 + 2 和 6 = 2 + 3, 就是重复的拆分方式。
输入格式:
一个正整数N(1≤N≤52)。
注意:本题N的上限52,是经过PTA平台服务器测试后得到的上限,能够保证较好的搜索策略在PTA提交,在1s内求解。本地PC机上,即使较好方法运行时间也可能大于1s,如果觉得方法没问题,可以先提交试试。
输出格式:
按照拆分方案的字典序由小大到大,输出所有方案,请参考输出样例
输入样例:
在这里给出一组输入。例如:
6
结尾无空行
输出样例:
在这里给出相应的输出。例如:
6=1+1+1+1+1+1
6=1+1+1+1+2
6=1+1+1+3
6=1+1+2+2
6=1+1+4
6=1+2+3
6=1+5
6=2+2+2
6=2+4
6=3+3
6=6
结尾无空行
- 知识点: dfs,暴力,回溯,剪枝。
思路:
-
用dfs进行搜索,判定条件sum=n,这里要用vector
进行存储,方便输出和回溯。 -
进行深搜时要升序进行搜索(不降序)因此dfs(sum,prenum)要有一个当前数的参数。
-
下一次进行搜索时i要从prenum开始。
自我纠正:
- 当找到sum==n时sum不需要归零,vector也不需要清零,但是在搜索时要进行回溯方便下一次寻找。
源码:
#include<bits/stdc++.h>
using namespace std;
int n;
vector<int> v;
vector<int> ::iterator it;
void dfs(int sum, int prenum) {
if (sum >= n) {
if (sum > n) {
//sum = 0;
//v.clear();
return;
}
cout << n << "=";
for (it = v.begin();it != v.end();it++) {
if (it != --v.end())
cout << *it << "+";
else
cout << *it << endl;
}
//sum = 0;
//v.clear();
return;
}
for (int i = prenum;sum + i <= n;i++) {
v.push_back(i);
dfs(sum + i, i);
v.pop_back();
}
}
int main() {
cin >> n;
dfs(0, 1);
}