演算法 0 1揹包(跳躍點解法)

2021-09-29 12:09:20 字數 3528 閱讀 6425

由m(i,j)的遞迴式容易證明,在一般情況下,對每乙個確定的i(1≤i≤n),函式m(i,j)是關於變數j的階梯狀單調不減函式。跳躍點是這一類函式的描述特徵。在一般情況下,函式m(i,j)由其全部跳躍點唯一確定。如圖所示。

對每乙個確定的i(1≤i≤n),用乙個表p[i]儲存函式m(i,j)的全部跳躍點。表p[i]可依計算m(i,j)的遞迴式遞迴地由表p[i+1]計算,初始時p[n+1]=。

乙個例子:n=3,c=6,w=,v=。

舉個栗子:

n=5,c=10,w=,v=。跳躍點的計算過程如下:

初始時p[6]=

因此,q[6]=p[6]⊕(w[5],v[5])=

p[5]=

q[5]=p[5]⊕(w[4],v[4])=

p[4]=   p[5]與q[5]的並集p[5]∪q[5]=中跳躍點(5,4)受控於跳躍點(4,6)。將受控跳躍點(5,4)清除後,得到p[4]

q[4]=p[4]⊕(6,5)=

p[3]=

q[3]=p[3]⊕(2,3)=

p[2]=

q[2]=p[2]⊕(2,6)=

p[1]=

p[1]的最後的那個跳躍點(8,15)即為所求的最優值,m(1,c)=15

演算法思想:

先在 p(i-1)的元素 j 上得到乙個新狀態,然後 w 小於它的不受影響,直接搬,w 等於它的,對 v 取大更,w 大於它的,根據 v 值直接pass 掉 不合法的點(w 大但 v 小於前邊的),同時,出現了新狀態往裡寫的時候,也要注意,w 大 v 也大時才合法,才可以往裡寫,反之直接扔掉。(在跳躍點函式影象中,保留的的是 max ,即p(i-1),q(i-1)倆函式圖取 max 的合圖)

記錄好錶之後,從終態開始往回倒找解路徑即可。

#include

using

namespace std;

const

int n =5;

template

<

class

type

>

intknapsack

(int n,type c,type v[

],type w,

int*

*p,int x)

;template

<

class

type

>

void

traceback

(int n,type w[

],type v[

],type *

*p,int

*head,

int x)

;int

main()

,w=;

//下標從1開始

int x[n+1]

;int

**p =

newint*[

50];for

(int i=

0; i<

50; i++

) cout<<

"待裝物品重量分別為:"

<

for(

int i=

1; i<=n; i++

) cout<

cout<<

"待裝物品價值分別為:"

<

for(

int i=

1; i<=n; i++

) cout<

cout<<

"揹包能裝的最大價值為:"

<<

knapsack

(n,c,v,w,p,x)

<

cout<<

"揹包裝下的物品編號為:"

<

for(

int i=

1; i<=n; i++)}

cout<

for(

int i=

0; i<

50; i++

)delete

p;return0;

}template

<

class

type

>

intknapsack

(int n,type c,type v[

],type w,

int*

*p,int x)

//如果 p[k][0]==y而mif

(k<=right && p[k][0

]==y)

k++;}

// 若p[k][0]>=y且m> =p[k][1],判斷是不是當前i的最後乙個跳躍點的受控點

//若不是則為i的跳躍點儲存

if(m>p[next-1]

[1])

//若是,則對下乙個元素進行判斷。

while

(k<=right && p[k][1

]<=p[next-1]

[1])

}while

(k<=right)

left = right +1;

right = next -1;

// 第i-1個物品第乙個跳躍點的位置 head[n]指第n個物品第乙個跳躍點的位置

head[i-1]

= next;

} cout<<

"head:"

<

for(

int i=

0;i<=n+

1;i++

) cout<<

"p[6-1]:"

<

for(

int i=

0;i1;i++

)traceback

(n,w,v,p,head,x)

;return p[next-1]

[1];

}//x陣列儲存對應物品0-1向量,0不裝入揹包,1表示裝入揹包

template

<

class

type

>

void

traceback

(int n,type w[

],type v[

],type *

*p,int

*head,

int x)}}}

執行效果:

動態規劃01揹包問題之跳躍點解法

m i j ma xm i,j max m i,j max m i j 代 表餘量j 從第乙個 物品到第 i個物品 的最優價 值m i,j 代表餘量j從第乙個物品到第i個物品的最優價值 m i,j 代表餘量 j從第一 個物品到 第i個物 品的最優 價值p i 代表m i,j 的跳躍 點點 集p i ...

01揹包問題 C 解法

01揹包問題 假設現有容量m的揹包,有i個物品,重量分別為w 1 w 2 w i 價值分別為p 1 p 2 p i 將哪些物品放入揹包可以使得揹包的總價值最大?最大價值是多少?示例1 m 10,i 3,物品重量 價值 3 4 4 5 5 6 第一種 不帶備忘的自頂向下法 using system n...

0 1揹包的遞迴解法

1 輸入物品個數n,揹包容量w 2 定義物品價值列表v,物品體積列表w 3 def rec i,j 從第i個物品開始挑選總重小於j的部分 4 res 0 5 if i n 剩餘物品為0 6 return res 7 elif j w i 無法挑選該物品 8 res rec i 1,j 9 else ...