問題描述:給定一個數組a和一個整數sum,在數組中取若干個數使得他們的和等於sum
問題分析:數組中的元素要麼選擇,要麼不選,且無序,每一種選擇都可以看做是解空間的一個元素
X[i] = 0或1(0<i<n, n爲數組a的長度)
如果我們假設當前已經處理了前t個元素(這t個元素或者選,或者不選),他們的和爲c,那麼在處理第t+1個元素時,要滿足c + a[t+1] < sum,否則,該元素選擇進去之後由於所有的數組元素都是正數,該和必定大於sum了,故該約束條件可以用來減枝,並且,我們注意到,如果c + (除前t個元素剩下所有元素的和) < sum 表示即使剩下的數組元素都選中也不可能達到sum,那麼,這條枝丫也可以減去,因爲不管怎麼選也不可能產生解,我們可以將數組從大到小排序,這樣就可以勁量多減枝了(留給讀者自己思考)
#include <iostream>
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;
}