青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

雁過無痕

  C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::

多重背包O(N*V)算法詳解(使用單調(diào)隊列)

 

多重背包問題:

N種物品和容量為V的背包,若第i種物品,容量為v[i],價值為w[i],共有n[i]件。怎樣裝才能使背包內(nèi)的物品總價值最大?

 

網(wǎng)上關(guān)于“多重背包”的資料倒是不少,但是關(guān)于怎么實現(xiàn)O(N*V)算法的資料,真得好少呀,關(guān)于“單調(diào)隊列”那部分算法,又沒說明得很清楚,看了幾遍沒看懂原理,只好自己動腦去想怎么實現(xiàn)O(N*V)算法。

 

若用F[i][j]表示對容量為j的背包,處理完前i種物品后,背包內(nèi)物品可達到的最大總價值,并記m[i] = min(n[i], j / v[i])。放入背包的第i種物品的數(shù)目可以是:012……,可得:

F[i][j] = max { F[i - 1] [j – k * v[i] ] + k * w[i] }  (0 <= k <= m[i])      

   

如何在O(1)時間內(nèi)求出F[i][j]呢?

先看一個例子:取m[i] = 2, v[i] = v, w[i] = w, V > 9 * v

并假設(shè) f(j) = F[i - 1][j],觀察公式右邊要求最大值的幾項:

j = 6*v:   f(6*v)f(5*v)+wf(4*v)+2*w 這三個中的最大值

j = 5*v:   f(5*v)f(4*v)+wf(3*v)+2*w 這三個中的最大值

j = 4*v:   f(4*v)f(3*v)+wf(2*v)+2*w 這三個中的最大值

顯然,公式㈠右邊求最大值的幾項隨j值改變而改變,但如果將j = 6*v時,每項減去6*wj=5*v時,每項減去5*wj=4*v時,每項減去4*w,就得到:

j = 6*v:   f(6*v)-6*wf(5*v)-5*wf(4*v)-4*w 這三個中的最大值

j = 5*v:   f(5*v)-5*wf(4*v)-4*wf(3*v)-3*w 這三個中的最大值

j = 4*v:   f(4*v)-4*wf(3*v)-3*wf(2*v)-2*w 這三個中的最大值

很明顯,要求最大值的那些項,有很多重復(fù)。

 

根據(jù)這個思路,可以對原來的公式進行如下調(diào)整:

假設(shè)d = v[i]a = j / db = j % d,即 j = a * d + b,代入公式㈠,并用k替換a - k得:

F[i][j] = max { F[i - 1] [b + k * d] - k * w[i] } + a * w[i]   (a – m[i] <= k <= a)   

 

F[i - 1][y] y= b  b+d  b+2d  b+3d  b+4d  b+5d  b+6d    j

F[i][j]就是求j的前面m[i] + 1個數(shù)對應(yīng)的F[i - 1] [b + k * d] - k * w[i]的最大值,加上a * w[i],如果將F[i][j]前面所有的F[i - 1][b + k * d] – k * w放入到一個隊列,那么,F[i][j]就是求這個隊列最大長度為m[i] + 1時,隊列中元素的最大值,加上a * w[i]因而原問題可以轉(zhuǎn)化為:O(1)時間內(nèi)求一個隊列的最大值

該問題可以這樣解決:

① 用另一個隊列B記錄指定隊列的最大值(或者記錄最大值的地址),并通過下面兩個操作保證隊列B的第一個元素(或其所指向的元素)一定是指定隊列的當(dāng)前最大值。

② 當(dāng)指定隊列有元素M進入時,刪除隊列B中的比M小的(或隊列B中所指向的元素小等于M的)所有元素,并將元素M(或其地址)存入隊列B

③ 當(dāng)指定隊列有元素M離開時,隊列B中的第一個元素若與M相等(或隊列B第一個元素的地址與M相等),則隊列B的第一個元素也離隊。

經(jīng)過上述處理,可以保證隊列B中的第一個元素(或其指向的元素)一定是所指定隊列所有元素的最大值。顯然隊列B的元素(或其所指向的元素)是單調(diào)遞減的,這應(yīng)該就是《背包九講》中的提到的“單調(diào)隊列”吧,初看的時候被這個概念弄得稀里糊涂,網(wǎng)上的資料提到“維護隊列的最大值”,剛開始還以為是維護這個單調(diào)隊列的最大值,對其采用的算法,越看越糊涂。其實,只要明白用一個“輔助隊列”,求另一個隊列的最值,那么具體的算法,和該“輔助隊列”的性質(zhì)(單調(diào)變化),都很容易推導(dǎo)出來。

在多重背包問題中,所有要進入隊列的元素個數(shù)的上限值是已知的,可以直接用一個大數(shù)組模擬隊列。

“多重背包”通用模板



多重背包特例:物品價值和體積相等(w = v)

由于w = v,上面的代碼可進行如下修改:

入隊的元素: tt = f[k] - (k / v) * w = f[k] - (k - j) = f[k] - k + j

    返回的最大值:*qb + (k / v) * w =  *qb + k - j

由于j是定值,可調(diào)整入隊的元素為: f[k] - k,最大值為 *qb + k

 

但這種做法相當(dāng)?shù)托А嶋H上,這相當(dāng)于一個“覆蓋”問題:在放入前i個物品后,體積為j的背包,只存在兩種狀態(tài):是否能剛好裝滿,也就是,是否能被覆蓋。因而只要記錄下該狀態(tài)就可以了,前面的分析進行相應(yīng)的調(diào)整:

F[i - 1][y] y= b  b+d  b+2d  b+3d  b+4d  b+5d  b+6d    j

F[i][j]就是求j的前面m[i] + 1個數(shù)對應(yīng)的F[i - 1] [b + k * d](其值為01)的最大值,即j前面的m[i] + 101數(shù)據(jù)中是否存在1,這又可以簡化為判斷它們的和是否不等于0


pack-01

 

另外,可以倒著讀數(shù)據(jù),這樣就不需要額外使用一個數(shù)組存放臨時數(shù)據(jù):


pack-02

 

前面的代碼,都在循環(huán)中對隊列的元素個數(shù)進行判斷,這可以通過下面的方法避免,將循環(huán)拆分成兩部分:一部分都有入隊和出隊操作、另一部分只有入隊(或出隊)操作。

 

對該特例,還有一種O(N * V)解法:用一個數(shù)組記錄當(dāng)前物品已經(jīng)使用數(shù),關(guān)鍵代碼:

if (! f[i] && f[i - v] && count[i - v] < n)

f[i] = true, count[i] = count[i - v] + 1;

每計算一類物品,count數(shù)組都要初始化一次,比較費時,可以再用一個數(shù)組記錄上一次處理的物品編號,通過判斷上一次放入那一類的物品編號與當(dāng)前這類物品編號是否一致(不一致時,相當(dāng)于count[i]值為0的情況),從而避免對count數(shù)組的初始化操作。還可以將初始化count數(shù)組和后面的循環(huán)整合在一起。


pack-1

pack-2

pack-4


POJ 1742
:有若干不同面值的紙幣,問能組合出1m中的幾種面值?


poj 1742

用自己隨機生成的數(shù)據(jù)測試了下,上面提到的幾種方法,所用時間都是7秒多點,有排序的比沒排序的稍微快點。但在POJ上提交的結(jié)果,不同代碼的耗時相差挺大,快的在1秒左右,慢的接近1.5秒。

 


還有一種特例:

給定面值為125的紙幣若干個,問其所不能支付的最低價格(假設(shè)為自然數(shù))。

這可以用多重背包(或母函數(shù))來解決,但實際上是有O(1)解法的。

posted on 2010-09-01 23:25 flyinghearts 閱讀(6546) 評論(5)  編輯 收藏 引用 所屬分類: 算法

評論

# re: 多重背包O(N*V)算法詳解(使用單調(diào)隊列) 2010-10-02 11:56 040374
能把用單調(diào)隊列解poj1742的思想寫得更詳細(xì)點嗎?thx  回復(fù)  更多評論
  

# re: 多重背包O(N*V)算法詳解(使用單調(diào)隊列) 2010-10-04 18:44 flyinghearts
@040374
在V=W這種特例中,單調(diào)隊列是可以不用的,只要采用隊列思想就可以了。
對每個值只記錄兩種狀態(tài),要判斷的是:(間隔為v)的連續(xù)n個狀態(tài)中是否為1,這等價于判斷它們的和是否不為0,
如果從前往后讀取這些狀態(tài)時,就需要一個臨時數(shù)組,不然新狀態(tài)值會覆蓋舊狀態(tài)值。
但是,我們可以從后往前讀取這些狀態(tài)值,這樣就不需要臨時數(shù)組了。

對V=W這種特例,“狀態(tài)+計數(shù)”(這也是很多網(wǎng)友采取的方法)這種方法,效率會更高,
一般來說,在判斷狀態(tài)中后期,狀態(tài)為真的占大多數(shù),這樣采用計數(shù)的方法就只要訪問某個狀態(tài)值一次,
而上面的方法,則要兩次(進出隊各一次)。

  回復(fù)  更多評論
  

# re: 多重背包O(N*V)算法詳解(使用單調(diào)隊列)[未登錄] 2012-11-16 11:11 kai
前面部分講的很清楚,謝謝

多重背包特例:物品價值和體積相等(w = v)

tt = f[k] - (k / v) * w = f[k] - (k - j) = f[k] - k + j

好像沒說清楚

改成

因為
F[i - 1] [b + k * d] - k * w[i]

d = w



b + k * d = k'
->
k = (k' - b)/d
->
tt = f[k'] - ( (k' - b)/ d) * w = f[k'] - (k'-b) = f[k'] - k' + b

在循環(huán)
for (int k = j, i = 0; k <= V; k += v, ++i)

里面

b其實是j, k' 其實是k

f[k'] - k' + b = f[k] - k + j
  回復(fù)  更多評論
  

# re: 多重背包O(N*V)算法詳解(使用單調(diào)隊列)[未登錄] 2012-11-18 06:01 kai
> 另外,可以倒著讀數(shù)據(jù),這樣就不需要額外使用一個數(shù)組存放臨時數(shù)據(jù):

正向著來為什么不可以?好像也說的通吧  回復(fù)  更多評論
  

# re: 多重背包O(N*V)算法詳解(使用單調(diào)隊列) 2014-10-12 09:59 天天好贏錢
有入口簡而言之是指在發(fā)布站點的相關(guān)頻道可以看到軟文標(biāo)題,點擊標(biāo)題進入www.fuc688.com軟文內(nèi)容頁面;而無入口則是指只提供文章內(nèi)容的網(wǎng)址鏈接,在頻道頁面找不到軟文標(biāo)題。有入口的軟文有助于線上網(wǎng)友的瀏覽,提高點擊率,可更好地擴大宣傳面;無入口的軟文適合做成書面的形式,用word或ppt等做成效果圖表,適用于線下的講座、匯報等。我們發(fā)布的軟文發(fā)布絕大部分都  回復(fù)  更多評論
  

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久久高清一区二区三区| 亚洲视频视频在线| 欧美日韩成人在线播放| 久久先锋影音| 久久午夜色播影院免费高清| 久久国产精品亚洲va麻豆| 久久伊人免费视频| 欧美精品福利| 国产精品三级久久久久久电影| 国产情人节一区| 91久久线看在观草草青青| 一本一本久久a久久精品综合麻豆 一本一本久久a久久精品牛牛影视 | 一区二区三区欧美在线| 在线亚洲+欧美+日本专区| 午夜一区二区三区不卡视频| 91久久精品视频| 欧美成人激情视频| 欧美日韩国产色站一区二区三区| 欧美调教视频| 狠狠色狠色综合曰曰| 亚洲人被黑人高潮完整版| 亚洲手机成人高清视频| 美女免费视频一区| 最新中文字幕一区二区三区| 一区二区日韩伦理片| 久久超碰97人人做人人爱| 欧美日本一区二区三区| 国产色婷婷国产综合在线理论片a| 在线观看欧美激情| 亚洲欧美美女| 欧美电影免费| 性亚洲最疯狂xxxx高清| 欧美激情综合网| 国产主播精品| 亚洲欧美韩国| 亚洲久久在线| 麻豆精品一区二区综合av| 国产欧美日本一区二区三区| 亚洲神马久久| 亚洲黑丝在线| 欧美成人精品福利| 在线观看欧美| 久久精品国产免费看久久精品| 亚洲另类一区二区| 欧美v日韩v国产v| 激情av一区| 久久福利精品| 欧美一进一出视频| 国产精品裸体一区二区三区| 日韩午夜av电影| 欧美高清自拍一区| 久久人人爽爽爽人久久久| 国产精品二区二区三区| 亚洲综合电影一区二区三区| 亚洲黄色在线| 欧美日韩激情网| 在线视频日本亚洲性| 9色精品在线| 欧美日韩日日夜夜| 亚洲午夜一区| 亚洲欧美日韩视频二区| 国产精品久久久久一区| 亚洲欧美bt| 亚洲欧美在线免费| 狠狠色综合网站久久久久久久| 久久久999精品免费| 久久精品30| 亚洲大片av| 欧美激情第9页| 欧美~级网站不卡| 中文av一区特黄| 亚洲欧美在线aaa| 韩国三级电影久久久久久| 葵司免费一区二区三区四区五区| 欧美福利在线观看| 老司机aⅴ在线精品导航| 亚洲国产精品123| 欧美黄色免费| 99热这里只有成人精品国产| 亚洲精选国产| 国产欧美日韩在线视频| 久久免费高清视频| 久久一区中文字幕| 99国内精品| 亚洲欧美国产另类| 激情成人av| 一本大道久久精品懂色aⅴ| 国产日产欧产精品推荐色 | 欧美一级播放| 久久一区二区三区四区| 亚洲精品欧美日韩专区| 亚洲伦伦在线| 国产三级精品三级| 亚洲国产精品成人一区二区 | 国产精品久久久久影院色老大 | 欧美精品v国产精品v日韩精品| 亚洲永久免费视频| 久久久夜夜夜| 亚洲欧美日韩综合| 老司机久久99久久精品播放免费| 亚洲综合电影| 美女福利精品视频| 午夜欧美精品| 欧美国产高潮xxxx1819| 性欧美大战久久久久久久免费观看 | 尤妮丝一区二区裸体视频| 91久久久久久国产精品| 国产欧美一区二区色老头| 亚洲国产日韩欧美在线99| 国产精品亚洲综合色区韩国| 欧美激情在线观看| 国产一区二区三区在线观看网站| 久久精品国产99国产精品| 久久精品成人一区二区三区| 亚洲一区在线免费观看| 久久一区激情| 欧美日韩一区二区在线观看| 亚洲第一中文字幕在线观看| 久久久久国产精品一区三寸| 亚洲理伦在线| 欧美在线视频a| 午夜精品一区二区在线观看 | 久久久久国产免费免费| 欧美日韩亚洲一区二区三区| 免费在线亚洲欧美| 国内精品久久久久影院优| 一区二区三区**美女毛片| 亚洲人线精品午夜| 久久天天躁狠狠躁夜夜av| 亚洲国产精品精华液2区45| 亚洲视频免费在线观看| 欧美风情在线| 欧美二区视频| 亚洲福利国产精品| 久久国产精品久久国产精品| 午夜精品剧场| 国产精品一区免费观看| 一区二区高清在线观看| 日韩一级免费| 欧美日韩一区二区三区| 亚洲日本欧美在线| 在线一区观看| 国产精品久久久久久久久动漫 | 亚洲午夜av电影| 欧美日韩一区二区三区四区在线观看 | 久久综合亚洲社区| 欧美www视频| 亚洲欧美中文另类| 欧美午夜一区二区福利视频| 亚洲毛片在线| 一区二区三区四区五区精品视频 | 中国成人在线视频| 欧美三级视频| 亚洲自拍啪啪| 久久人人97超碰国产公开结果 | 亚洲精品一级| 欧美日韩国产大片| 久久国产精品黑丝| 欧美激情成人在线| 久久中文字幕一区| 欧美在线黄色| 免费久久99精品国产自| 在线日韩中文| 欧美激情精品久久久久久免费印度| 亚洲激情视频在线观看| 91久久视频| 欧美色大人视频| 亚洲免费观看视频| 欧美亚洲视频一区二区| 激情六月婷婷综合| 欧美母乳在线| 欧美一级午夜免费电影| 亚洲国产精品日韩| 欧美亚洲一区在线| 国产一区日韩欧美| 欧美精品一区二区在线观看| 亚洲欧美日韩视频一区| 亚洲电影免费观看高清完整版| 亚洲美女区一区| 亚洲精品孕妇| 亚洲国产精品一区二区第一页 | 欧美日韩伦理在线免费| 亚洲综合国产激情另类一区| 免费在线日韩av| 午夜一级久久| 在线亚洲一区观看| 最新日韩欧美| 国产主播一区二区三区| 欧美性猛交视频| 欧美第一黄色网| 久久精品视频99| 亚洲综合日韩在线| 日韩视频在线免费| 亚洲国产免费看| 麻豆精品视频| 久久久久久精| 久久国产精品久久久久久电车| 亚洲香蕉成视频在线观看| 亚洲精品久久久蜜桃| 在线日韩av片|