PTA 子集和问题(回溯法):给定集合S,S中有n个正整数,M是一个正整数。...

问题
给定集合S,S中有n个正整数,M是一个正整数。子集和问题判定是否存在S的一个子集S1,使得S1中各元素之和等于M。请设计回溯法求解子集和问题,如果问题无解,输出“No Solution”,问题有解,则输出满足子集S1中各元素的值。

输入样例

4 31
13 24 11 7

输出样例

13 24 11 7
24 7

详解请看代码注释

源代码

#include<iostream>

using namespace std;

int* arr,*result;                  // arr表示数据数组;result表示解数组,用于存储解向量
int M, n, sum=0, cnt=0;            // M表示目标正整数,n表示集合中的元素个数,cnt表示解的个数
void backTrack(int k) {
	if (sum > M || k > n) {
		return;
	}
	if (sum == M) {                // 找到符合条件的解集,输出
		cnt++;                     // 解个数+1
		for (int i = 0; i < n; i++) {
			if (result[i] == 1) {  // 解数组内,1表示该数(arr[i])存在于子集和中
				cout << arr[i] << " ";
			}
		}
		cout << endl;
	}
	else {                         // 未符合条件,继续
		for(int i=0;i<=1;i++){     // i=0表示该数arr[k]未装入解集。i=1表示已装入
			if (i==0) {
				sum = sum + arr[k];// 装入该数
				result[k] = 1;     // 更改标记为已装入
				backTrack(k + 1);  // 继续下一个数
				result[k] = 0;     // 回溯回来后,更改该数标记为未装入
				sum = sum - arr[k];// 将该数移出目标子集和
			}
			else {
				backTrack(k + 1);  // 该数已装入,继续下一个数
			}
		}
	}
}

int main() {
	cin >> n>>M;                   // 输入集合元素个数n和目标正整数M
	arr = new int[n];
	result = new int[n];
	for (int i = 0; i < n; i++) {  // 输入集合元素数据
		cin >> arr[i];
	}
	for (int i = 0; i < n; i++) {  // 初始化解数组
		result[i] = 0;
	}
	backTrack(0);                  // 进入回溯
	return 0;
}

版权声明:本文为qwqc262原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。