子集和数问题 C++程序实现 回溯

/*  Function : 求子集和数问题 
 *  Author   : wyh7280 
 *  Time     : 2015.05.20   10:16:00.000
 *  Note     : 注意输入的集合arr(即函数中的w[i],应确保是单调递增的,如果不是,请在该程序基础上建立结构体,存储每个集合元素 
 *             原先的编号,并根据集合元素值的大小进行排序。 
 */
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <cstring>
using std::cin;
using std::cout;
using std::endl;

//求解函数 
void sumOfSub(float s, int k, float r, int *x, float m, float *w); 
void sumOfSub(int *x, int n, float m, float *w);

int main()
{
	int n;            					 //n表示集合元素个数
	float m;          					 //m表示目标和 
	cout << "请输入集合元素个数:";
	cin >> n;
	cout << "请输入目标和:"; 
	cin >> m;
	float *arr = new float [n + 1];
	int *x = new int [n + 1];           //求解状态 
	cout << "请输入" << n <<"个集合元素(正值):"; 
	for(int i=0; i < n; i++) 
	{
		 cin >> arr[i]; 
	}
	cout << "可行解:
"; 
	sumOfSub(x, n, m, arr);
	
	return 0;
}

void sumOfSub(float s, int k, float r, int *x, float m, float *w)
{
	x[k] = 1;
	if(s + w[k] == m)										//一个可行解 
	{ 
		for(int j = 0;j <= k; j++)    //两种输出方式任选 
		{
			//cout << x[j] << " ";    //完成输出,输出每个元素是否选取的状态,为1表示选取,为0表示未选 
			if(x[j] == 1)             //完成输出,输出选取的元素 
			  cout << w[j] << " ";
		}
		cout << endl;
	}
	else if(s + w[k] + w[k+1] <= m)
	{
		sumOfSub(s+w[k], k+1, r-w[k], x, m, w);			   //搜索左子树 
	} 
	if((s + r - w[k] >= m)&&(s + w[k]+1 <= m))
	{
		x[k] = 0;
		sumOfSub(s, k+1, r - w[k], x, m, w);  			   //搜索右子树 
	}
}
void sumOfSub(int *x, int n, float m, float *w)
{
	float r = 0;
	for(int i = 0; i < n; i++)  r += w[i];                //计算总值,判断是否有解 
	
	if(r >= m && w[0] <= m)  sumOfSub(0, 0, r, x, m, w); 
}


回溯法的常用例子

版权声明:本文为博主原创文章,未经博主允许不得转载。

原文地址:https://www.cnblogs.com/Tobyuyu/p/4965392.html