完全揹包練習之鋼條切割問題

2021-08-06 00:22:57 字數 2767 閱讀 9543

/* 

name: 鋼條切割問題

author: 巧若拙

description: 給定一段長度為n英吋的鋼條和乙個**表 pi (i=1,2, …,n),求切割鋼條的方案,使得銷售收益rn最大。

注意,如果長度為n英吋的鋼條**pn足夠大,最優解可能就是完全不需要切割。

若鋼條的長度為i,則鋼條的**為pi,如何對給定長度的鋼條進行切割能得到最大收益?

長度i 1 2 3 4 5 6 7 8 9 10

**pi 1 5 8 9 10 17 17 20 14 30

i = 1時,鋼條不可切割,r[1]= 1;

i = 2時,鋼條可分割為1+ 1,其**為2。若不分割(0 + 2),**為5。即r[2] = 5;

i = 3時,鋼條可分割為0+ 3,1 + 2。r[3] = 8;

同理可得:

r[4] = 10(2+ 2);

r[5] = 13(2+ 3);

r[6] = 17(0+ 6);

r[7] = 18(1+ 6或4+ 3=> 2 + 2 + 3);

.......

我們可以發現,長度為7時,將其切割為長度4與長度3的鋼條,並對兩個鋼條分別求最優解:

長度4的最優解為r[4] = 10(2 + 2),長度3的最優解為r[3] = 8,即可得r[7] =r[4]+ r[3] =>原問題的最優解等於子問題的最優解之和的最大值

我們將鋼條左邊切割下長度為 i 的一段,只對右邊剩下的長度為 n-i 的一段繼續進行切割(遞迴求解),對左邊的一段不再進行切割。

即問題分解的方式為:將長度為n 的鋼條分解為左邊開始一段,以及剩餘部分繼續分解的結果。

這樣,不做任何切割的方案就可以描述為:第一段的長度為n ,收益為 pn,剩餘部分長度為0,對應的收益為r0=0。於是公式的簡化版本:

因此,在計算r[i]時,所求值即為r[0] +r[i],r[1]+ r[i-1],r[2]+ r[i-2],... ,r[i-1] +r[1] 之間的最大值,

而在動態規劃中,r[0]--r[i-1]的值在計算r[i]之前已經儲存好了,進行少量的運算便能取得最優結果。

這個是典型的完全揹包問題,相當於共有n個物品,物品的重量wi分別是1-n,價值為pi,揹包總容量為n,求最大價值。

*/

#include#include#includeusing namespace std;

const int maxc = 10000; //揹包最大容量

const int maxn = 10000; //物品的最大個數

int w[maxn+1];//物品的重量

int p[maxn+1];//物品的價值

int b2[maxn+1][maxc+1]; //記錄給定n個物品裝入容量為c的揹包的最大價值

int b4[maxc+1]; //記錄最優解

int x[maxn+1]; //記錄裝入揹包中的物品編號及其數量

int completepack_2(int n, int c);//動態規劃:f[i][j] = max(f[i-1][j], f[i][j-w[i]] + p[i])

int completepack_4(int n, int c);//優化的動態規劃演算法,一維陣列儲存記錄

void show(int i, int j); //i和j分別表示正在處理的第i個物品和此時揹包的剩餘容量

int show_2(int n, int c); //利用陣列b2,輸出物品裝載情況,並返回實際裝載量,x[i]初始化為0

int main()

while (p[i] <= p[i-1]);

printf("%d ", p[i]);

w[i] = i;

} c = n;

//動態規劃:二維陣列儲存記錄,需要用到全域性變數w, p, 另有b2[maxn+1]預設初始化為0

cout << completepack_2(n, c) << endl;

//優化的動態規劃演算法,一維陣列儲存記錄,需要用到全域性變數w, p, 另有b4初始化為0

cout << completepack_4(n, c) << endl;

//利用陣列b2,輸出物品裝載情況,x[i]初始化為0

cout << show_2(n, c) << endl;

//利用陣列b2,按照編號順序,遞迴輸出裝入揹包的物品資訊(編號,數量,重量,價值)

show(n, c);

return 0;

}int completepack_2(int n, int c)//動態規劃:f[i][j] = max(f[i-1][j], f[i][j-w[i]] + p[i]) }

return b2[n][c];

}int completepack_4(int n, int c)//進一步優化的動態規劃演算法,用1個一維陣列代替二維陣列 }

return b4[c];

}void show(int i, int j) //i和j分別表示正在處理的第i個物品和此時揹包的剩餘容量

else

}}}

int show_2(int n, int c) //利用陣列b2,輸出物品裝載情況,並返回實際裝載量,x[i]初始化為0

}} }

int s = 0;

for (int i=1; i<=n; i++)

} return s;

}

揹包問題之完全揹包

完全揹包 有n種物品,每種物品有無限個,每個物品的重量為w i 價值為v i 現在有乙個揹包,它所能容納的重量為c,問 你的揹包所能帶走的最大價值是多少?之前01揹包分析過了,如果是順序的話,就表示同一物品可以多次放入!這就是完全揹包!就是這麼神奇!1 include 2 3using namesp...

動態規劃之鋼條切割問題

鋼條切割方案自底向上 public class cutrodbottom2up public static void main string args private void start private cutrodsolution bottomupcutrod int n crsl.r j q ...

揹包問題(完全揹包)

1.矩陣鏈乘法 2.投資組合問題 3.完全揹包問題 4.01揹包問題 5.最長公共子串行 乙個揹包,可以放入n種物品,物品j的重量和價值分別為,如果揹包的最大重量限制是b,怎麼樣選擇放入揹包的物品以使得揹包的總價值最大?組合優化問題,設表示裝入揹包的第j個物品的數量,解可以表示為。那麼目標函式和約束...