《回溯法實驗報告》 計科2001 陳梓聰 20201003024
回溯法的思想:通過第五章學習了回溯法,我們知道回溯法總是遍歷所有可能性,相當於窮舉法,但是通常需要通過剪枝來降低算法的時間復雜度。
回溯法的局限性:回溯法的局限性較大,由於他相當於窮舉,所以時間復雜度較高,盡管我們能通過剪枝來降低,但是當數據規模大的時候,時間復雜度依然能達到指數級。
回溯法的分析過程:我們需要了解我們問題的解空間樹,然后確定我們可以剪枝的條件(也有可能是函數)。
4-1最小重量機器設計問題:
設某一機器由n個部件組成,每一種部件都可以從m個不同的供應商處購得。設wij是從供應商j 處購得的部件i的重量,cij是相應的價格。 試設計一個算法,給出總價格不超過d的最小重量機器設計。
輸入格式:設某一機器由n個部件組成,每一種部件都可以從m個不同的供應商處購得。設wij是從供應商j 處購得的部件i的重量,cij是相應的價格。 試設計一個算法,給出總價格不超過d的最小重量機器設計。
輸出格式:輸出計算出的最小重量,以及每個部件的供應商
輸入:
3 3 4
1 2 3
3 2 1
2 2 2
1 2 3
3 2 1
2 2 2
輸出:
4
1 3 1
#include <iostream> #include <cmath> using namespace std; int c[30][30], w[30][30], solve[30][30], pro[30], n, m, d, minw = 1000000, cerw, cerc; void backtrack(int t) { if (t > n) { if (cerw < minw && cerc <= d) { minw = cerw; for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { if (solve[i][j]) pro[i] = j; } } } return; } for (int i = 1; i <= m; i++) { if (cerc + c[t][i] <= d) { cerc += c[t][i]; cerw += w[t][i]; solve[t][i] = 1; if(cerw <= minw)backtrack(t + 1); solve[t][i] = 0; cerc -= c[t][i]; cerw -= w[t][i]; } } } int main() { cin >> n >> m >> d; for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { cin >> c[i][j]; } } for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { cin >> w[i][j]; } } backtrack(1); cout << minw << endl; for (int j = 1; j <= n; j++) { cout << pro[j] << " "; } }
剪枝:我的剪枝算法是之前所選物品價格加上當前物品的價格大於規定價格時剪枝,同時我記錄了之前遍歷節點的最小重量,若當前重量已經大於最小重量則剪枝。
心得與體會:回溯法思想簡單,但是數據量大的時候耗費時間多,使用的時候需謹慎考慮。