/*
name: 0-1揹包問題
author: 巧若拙
date: 07-03-17 15:30
description:
給定n中物品和乙個容量為c的揹包,物品i的重量為wi,其價值為vi,
0-1揹包問題是如何選擇裝入揹包的物品(物品不可分割),使得裝入揹包的物品的價值為最大。
1.題目分析:
考慮到每種物品只有2種選擇,即裝入揹包或不裝入揹包,並且物品數和揹包容量已給定,
要計算裝入揹包物品的最大價值和最優裝入方案,可用回溯法搜尋子集樹的演算法進行求解。
2.演算法設計:
a. 物品有n種,揹包容量為tc,建立乙個物品類,分別用w和p儲存物品的重量和**,
設定物件陣列a[n]儲存各個物品的重量和**資訊,
設定物件c和best分別記錄揹包當前儲存物品的資訊,和已經獲得的最優解資訊,
x[i]標記第i種物品是否裝入揹包,用bestx[i]儲存第i種物品的最優裝載方案;
b. 用遞迴函式backtrace(t)來實現回溯法搜尋子集樹(形式引數t表示遞迴深度):
① 若t == n,則演算法搜尋到乙個葉結點,判斷當前總價值是否最優:
1> 若c.p>best.p,更新當前最優解(即best=c),更新裝載方案(即bestx[i]=x[i]( 0≤i < n));
② 對物品i裝與不裝兩種情況進行討論,先分析裝t號物品的情形,再分析不裝t號物品的情形,這樣回溯到上一層時,
x[t]再次歸零,同時c不包含a[t],以便討論完上層結點後,再次分析結點t。
if(c.w <= tc && c.p+sum(t) > best.p) backtrace(t+1);繼續進行裝載;
③ 若已測試完所有裝載方案,外層呼叫就全部結束。
c. 主函式呼叫一次backtrace(0)即可完成整個回溯搜尋過程,
最終得到的bestp和bestx[i]即為所求最大總價值和最優裝載方案。
在非遞迴回溯中,我們用x[t]的值表示是第幾次訪問結點t,剛開始x[t]==0,
如果t == n,表示t為葉子結點的子孫(即不存在t號物品),判斷已裝載的物品是否為最優解,然後直接回溯。
否則先分析裝t號物品的情形,並令x[t] = 1;c.w += a[t].w;c.p += a[t].p;
再分析不裝t號物品的情形,並令x[t] = 2;c.w += a[t].w;c.p += a[t].p;這樣cw和cp的值就已經還原了
兩種情況都分析完後x[t]==2,通過語句x[t--] = 0; 來卸掉t號貨櫃並回溯到上層結點。
利用sum(int t);計算結點t的子樹結點**之和時,原來的演算法是把所有子孫結點的**都累積起來,這樣會比實際值大,
因為很有可能某些子孫結點超載,根本不能裝進去,而我們也把它的**累積進來了。
乙個改進演算法是將物品按照單位**排好序,單位**高的靠前,這樣如果某個物品超載時,沒必要再累積其後面物品的**,
而是按照該物品的單位**乘以剩餘容量,這樣算出的總**雖然比實際裝載的總**略高些,但總比全部都加進去更接近真實值,
而且也減少了計算量(後面的物品就不用再計算了)。
本例給出了改進後的演算法
3. 複雜度分析:
因為裝載問題解空間的子集樹中葉子節點的數目為2^n,因而最壞情況下時間複雜度為o(2^n)。 */
#include#include#includeusing namespace std;
class goods
bool operator < (const goods &b)const //遞減序
friend int sum(int t);//結點t的子樹結點**之和
friend void backtrace(int t); //遞迴回溯
friend void backtrace_2(); //非遞迴回溯
int w, p; //分別儲存物品的重量,**
};const int n = 4; //物品的個數
int x[n]; //解向量
int bestx[n]; //最優解解向量
vectora;
goods c, best;//分別記錄揹包當前儲存物品的資訊和已經獲得的最優解資訊
int tc = 10; //揹包總容量
int main()
if (i < n) //說明到a[i]就超載了,後面的物品無需再分析,直接按照a[i]的單位**乘以剩餘容量計算總價值
s += int(r * a[i].p * 1.0 / a[i].w);
return s;
}void backtrace(int t) //遞迴回溯
}void backtrace_2() //非遞迴回溯,用x[t]的值表示是第幾次訪問結點t
else //表示 x[t] == 2,已經分析完畢,該回溯到上一層結點了
}}
回溯 0 1揹包問題
回溯演算法的要點 1,針對所給問題,定義問題的解空間。2,確定容易搜尋的解空間的組織結構。3,通過剪枝優化搜尋過程。下面通過求解0 1揹包問題來分析使用回溯演算法的過程 1,根據問題的描述,設所有的物件數是n,對應的重量和價值分別為w 0 n 1 和v 0 n 1 於是這個問題就轉化成在這n件物件中...
回溯 01揹包問題
這裡再簡單寫一下問題要求 給定n中物品和乙個容量為c的揹包,物品i的重量為wi,其價值為vi,0 1揹包問題是如何選擇裝入揹包的物品 物品不可分割 使得裝入揹包的物品的價值為最大。1.題目分析 考慮到每種物品只有2 種選擇,即裝入揹包或不裝入揹包,並且物品數和揹包容量已給定,要計算裝入揹包物品的最大...
0 1揹包問題(回溯)
描述 需對容量為c 的揹包進行裝載。從n 個物品中選取裝入揹包的物品,每件物品i 的重量為wi 價值為pi 對於可行的揹包裝載,揹包中物品的總重量不能超過揹包的容量,最佳裝載是指所裝入的物品價值最高。輸入多個測例,每個測例的輸入佔三行。第一行兩個整數 n n 10 和c,第二行n個整數分別是w1到w...