问题描述:给定一个数组a和一个整数sum,在数组中取若干个数使得他们的和等于sum
问题分析:数组中的元素要么选择,要么不选,且无序,每一种选择都可以看做是解空间的一个元素
X[i] = 0或1(0
如果我们假设当前已经处理了前t个元素(这t个元素或者选,或者不选),他们的和为c,那么在处理第t+1个元素时,要满足c + a[t+1] < sum,否则,该元素选择进去之后由于所有的数组元素都是正数,该和必定大于sum了,故该约束条件可以用来减枝,并且,我们注意到,如果c + (除前t个元素剩下所有元素的和) < sum 表示即使剩下的数组元素都选中也不可能达到sum,那么,这条枝丫也可以减去,因为不管怎么选也不可能产生解,我们可以将数组从大到小排序,这样就可以劲量多减枝了(留给读者自己思考)
#include
using namespace std;
int m_count = 0;
void output(int a[], int x[], int m) {
for (int i = 0; i <= m; i++) {
if (x[i] == 1) {
cout << a[i] << " ";
}
}
cout << endl;
}
void BackTrack(int t, int a[], int x[], int s[], int n, int sum, int& c) {
++m_count;
if (t == n) {
return;
}
if (c + a[t] < sum && s[t] + c >= sum) {
x[t] = 1;
c += a[t];
BackTrack(t+1, a, x, s, n, sum, c);
c -= a[t];
x[t] = 0;
} else if (c + a[t] == sum) {
x[t] = 1;
output(a, x, t);
x[t] = 0;
}
BackTrack(t+1, a, x, s, n, sum, c);
}
int main() {
int a[10] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; //这里我就默认排序过了
int x[10] = {0};
int s[10] = {0};
int sum = 15;
int c = 0;
s[9] = 1;
for (int i = 8; i >= 0; i--) {
s[i] = s[i+1] + a[i];
}
BackTrack(0, a, x, s, 10, sum, c);
cout << "执行了" << m_count << "次" << endl;
return 0;
}