用回溯法解決子集和問題 C 版本

2021-07-09 02:42:10 字數 1725 閱讀 9055

最近在開發某專案,遇到這樣乙個需求:在乙個賬單記錄的table中,記錄著每張賬單及其金額,要求使用者輸入乙個金額,從表中取出金額組合為該金額的賬單【可能有很多個解,但只需要提供一例】。

這題目看起來很簡單,只是把數加起來判斷,但仔細一想,難度不小。因為組合的個數沒有確定,可以直接找到,即1個,或者2個,3個……n個組成,那麼原先想要使用的for迴圈就無法使用了,因為不知道要巢狀多少層,而且跟後來的方法相比效率較低。

後來在網上查了好久,查到了這原來這叫做子集和問題,是什麼0-1揹包之類的問題【資料結構學得一般t^t】需要用遞迴或回溯解決。因為我只需要求出一解,所以我選擇了回溯法。遞迴將顯示所有組合,但我並不需要。下面是仿照別人的思路寫出的**,我將一一注釋。

1

static

void main(string

args)

2;//

測試用的陣列

4bool flag = ;//

標誌陣列,與測試陣列對應,true代表該數在組合中,false則不在

5   bubble(test);//

冒泡,其實不排序也可以

6int target =convert.toint32(console.read());

7bool result =backtrace(test, flag, target);89

if (result == true)10

, ", test[i]);15}

16}17else

1821

console.writeline();22}

2324

static

bool backtrace(int a, bool flag, int

target)

2542       index++;//

繼續檢驗下一元素43}

4445

//如果索引到了最後,還沒有找到合適的組合,那麼將回溯.一般來說會出現*100011或*1000的情況,即此時flag中的元素應該在某個1之後有若干個0或01組合【先0後1】, [i個數] 1 [j個0][k個1]這樣的情況,回溯到1的位置,將其變為0,然後繼續往下迴圈檢驗.從後面回溯的時候,將1變為0,遇0不變.如果回溯到首位,則說明沒有合適的組合存在.

4647

if (index >=a.length)

4857

58while (flag[index - 1] == false)//

如果不在組合中,往前回溯

5964       flag[index - 1] = false

;65       sum -= a[index - 1

];66}67

68}69return

false;70

71}7273

static

void bubble(int

a)7484}

8586

foreach (int k in

a)87   console.write(", "

, k);

88console.writeline();

89 }

還應注意console.readline(),讀入的是字串,要經過convert.toint32()的處理,因為輸入的是字串,其值與字面值不一致.

此外應該還可以再優化,但過幾個鐘還要上班,還是睡覺去吧.

ps:我不是通宵工作,我從10點睡到4點半,睡不著就起床寫一下部落格。程式設計師要記得勞逸結合哦!

子集和問題(回溯法)

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

子集和問題(回溯法)

給定乙個含有n個元素的整形陣列a,再給定乙個和sum,求出陣列中滿足給定和的所有元素組合,舉個例子,設有陣列a 6 sum 10,則滿足和為10的所有組合是 注意,這是個n選m的問題,並不是兩兩組合問題 最直觀的想法就是窮舉,把陣列中元素的所有組合情況都找出來,然後看看哪些組合滿足給定的和即可,這種...

用回溯法解決八皇后問題 C語言

問題描述 要求在8x8的西洋棋棋盤上放入八個皇后,使得任意兩個皇后不能處於同一列,同一行,同一條斜線上。演算法思路 1 判斷皇后之間有沒有衝突,要引入四個量 row 行號,也對應於皇后的編號 column 列號 slash 斜線方向 bslash 反斜線方向 2 由棋盤的布局可以發現,在斜線方向上有...