/* 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);
}
回溯法的常用例子
版权声明:本文为博主原创文章,未经博主允许不得转载。