7-7 自然数拆分问题 (60 分)

一个整数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
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);
}

你可能感兴趣的:(PTA测试题,剪枝,算法,c++,数据结构)