子集和問題(回溯法)

2021-10-06 12:25:48 字數 1585 閱讀 4488

給定乙個含有n個元素的整形陣列a,再給定乙個和sum,求出陣列中滿足給定和的所有元素組合,舉個例子,設有陣列a[6] = ,sum = 10,則滿足和為10的所有組合是

注意,這是個n選m的問題,並不是兩兩組合問題

最直觀的想法就是窮舉,把陣列中元素的所有組合情況都找出來,然後看看哪些組合滿足給定的和即可,這種方法的計算量非常大,是指數級的,假設陣列有n個元素,那麼所有組合的情況一共有2 ^ n種(包括空集),如果n很大的話,這個方法將會非常慢。那麼如何找出所有這些組合呢?其實對於任意乙個組合來講,陣列a中任意乙個元素要麼在這個組合中,要麼不在這個組合中,我們用1表示在,用0表示不在,那麼每一種組合實際上對應著乙個01序列,而這個序列對應著乙個十進位制數,一共有多少種這樣的序列呢?前面說了,是2 ^ n種,分別對應1 - 2 ^ n中的每乙個十進位制數,所以我們只需遍歷這些數字,確定哪些位是1,將陣列a中對應的數字放入組合中,再檢查一下這個組合的和是否為sum即可。舉個例子,在題目描述中我們說到a[6] = ,sum = 10,那麼

相當於 111100 (1, 2, 3, 4在組合中,而5, 6不在)

相當於101001

陣列a有6個元素,所以我們要搜尋64個數,只有上面的三種組合滿足條件,其他的全部淘汰。

**-輸出函式

// 輸出一種組合,該組合取決於引數i

// 將引數i寫成二進位制的形式,對於i中取值為1的位,取陣列a中對應的元素放到組合中

// n是陣列a中元素個數

// 在取a中元素的時候,方向是從後向前的,因為我們測試i中哪些位是1的時候是從右向左進行的。

void

output

(int

* a,

int n,

int i)

cout << endl ;

}

**-主函式
void

fixedsum

(int

* a,

int n,

int sum)

if(s == sum)

output

(a, n, i);}

}

首先定義乙個標誌位陣列flag,flag[i]如果為true,則表示a[i]在當前解中,如果flag[i]為false則表示不在。這個陣列元素個數與陣列a的元素個數相同。

bool flag[

100]

=;

**-輸出函式
//輸出一種組合,該組合有n個元素

void

output

(int

* a,

int n)

cout << endl ;

}

**-主函式
// a: 待搜尋的陣列

// n: 陣列元素個數

// t: 已經儲存的元素個數

// sum: 給定的和

void

fixedsum

(int

* a,

int n,

int t,

int sum)

}}

出處:

子集和問題(回溯法)

第五章5 1 子集和問題 實驗報告 一 問題分析 處理的物件 給定的集合元素的個數和集合以及要湊成的和 要實現的功能 對於給定的集合,計算出它的乙個子集,使得子集內元素的和等於給出的正整數。這乙個子集就是最先計算出的那個子集 演算法思想 當我們給出集合個數n和要湊成的和m以及n個集合元素,我們使用乙...

回溯法之子集和問題

問題描述 設集合s 是乙個正整數集合,c是乙個正整數,子集和問題判定是否存在s的乙個子集s1,使s1中的元素之和為c。試設計乙個解子集和問題的回溯法。將子集和問題的解輸出。當問題無解時,輸出 no solution 因為我在 裡的注釋已經寫了很多了,大家將就看著注釋理解哈 直接貼 includeus...

回溯法之子集和問題

include include using namespace std define m 100 class sumofsub void sumofsub backtrack int t printf n return else x t 0 backtrack t 1 void sumofsub f...