揹包問題之一(回溯法)
阿新 • • 發佈:2019-01-02
揹包問題分為很多種,其核心不過是尋找全部解或最優解的問題。
這篇文章就其中一個典型問題進行講解。
題目:一個容積為T的揹包,和n件體積不等的物品,選出若干件物品剛好裝滿揹包,列出所有的組合。
顯然回溯法可以解決這個問題。回溯法是一種選優搜尋法,又稱為試探法,按選優條件向前搜尋,以達到目標。但當探索到某一步時,發現原先選擇並不優或達不到目標,就退回一步重新選擇,這種走不通就退回再走的技術為回溯法,迷宮問題是這種方法最直觀典型的應用。
首先要藉助一個數組儲存全部物品,一個vector儲存一組滿足條件物品,再寫一個遞迴呼叫的函式selectgood(int rest, int position), rest是揹包剩餘的容積,position代表當前搜尋的位置。當搜尋到currentposition時,假設此時揹包剩餘容積為currentrest,那麼有兩種情況,一種是選擇不將當前物品放入揹包,則呼叫函式selectgood(currentrest,
currentposition+1),另一種情況是將當前物品放入揹包,但是在這種情況裡如果當前物品的體積大於currentrest,則不能繼續,如果不大於,則將當前物品放入vector,再判斷當前的rest,若揹包恰好裝滿,則輸出當前vector裡面的一組,若還未裝滿,則呼叫selectgood(currentrest,currentposition+1),最後當裝有當前物品的所有滿足情況輸出後,在函式最後將當前物品從vector取出。
程式碼:
#include<iostream> #include<vector> using namespace std; int count = 0; vector<int> mine; int all[100]; int T, n; void selectgood(int rest, int position) { if (rest == 0) return; if (position == n) return; selectgood(rest, position+1); if (rest < all[position]) return; mine.push_back(all[position]); if (rest == all[position]) { count++; vector<int>::iterator iter; for (iter = mine.begin(); iter != mine.end(); iter++) { cout << *iter << " "; } cout << endl; } selectgood(rest-all[position], position+1); mine.pop_back(); } int main() { cin >> T >> n; for (int i = 0; i < n; i++) { cin >> all[i]; } selectgood(T, 0); cout << "Totally " << count << " sets of solutions" << endl; }