1. 程式人生 > >揹包問題進階優雅總結【二維費用+分組+有依賴】

揹包問題進階優雅總結【二維費用+分組+有依賴】

目錄

作者有話說

小結

小結

分析

作者有話說

本篇博文中的各類陣列都從1開始

題目裡好像混進去了什麼奇怪的東西

二維費用的揹包問題

二維費用的揹包問題是指:對於每件物品,具有兩種不同的費用,選擇這件物品必須同時付出這兩種費用。對於每種費用都有一個可付出的最大值(揹包容量)。問怎樣 選擇物品可以得到最大的價值。

設第 i 件物品所需的兩種費用分別為 Ci 和 Di。兩種費用可付出的最大值(也即兩 種揹包容量)分別為 V 和 U。物品的價值為 Wi。

狀態定義及轉移

cost增加了一位,那麼狀態定義時也要增加一位

定義dp[i][j][k]表示前i種物品費用為j和k時的最大價值

轉移:\large dp[i][j][k]=max(dp[i-1][j][k],dp[i-1][j-c[i]][k-d[i]]+w[i])

同樣,也可以滾成二維,根據物品型別更新,如若每件物品只有一件,注意要倒序。

物品總個數的限制

(來源:揹包九講)

很多時候,第二維的限制條件並不是直接給出的,而是需要轉化,這也提示我們題目如果是在我們熟悉的基礎上增加了一些限制條件,則可以從“陌生中找到熟悉”(這好像是我語文老師說的,不管了,要融會貫通),對現有的條件進行轉化,然後根據模板切題(愉快地打板兒)

比如說 CF的Checkout Assistant 就是進行轉化而來的,意識到可以偷物品就是買這件物品,可以“送”ti件物品,相當於花這件物品的money,可以得到ti+1件物品,而目標是得到n件物品,然後就是0-1揹包板題。

小結

當發現由熟悉的動態規劃題目變形得來的題目時,在原來的狀態中加一維以滿足新 的限制是一種比較通用的方法。

(來源:揹包九講)

分組的揹包問題

有 N 件物品和一個容量為 V 的揹包。第 i 件物品的費用是 Ci,價值是 Wi。這些物品被劃分為 K 組,每組中的物品互相沖突,最多選一件。求解將哪些物品裝入揹包可使這些物品的費用總和不超過揹包容量,且價值總和最大。

狀態定義及轉移

這類問題的決策則要對於每組物品進行,對於每一組物品可以一個都不選,也可以選第1個、第2個、第3個······

則狀態定義及轉移也十分好想。定義dp[k][j]為前k組物品重量不超過j的最大價值

轉移需要三層for:列舉組數、列舉重量、列舉組中的每一件物品。

\large dp[k][j]=max\begin{Bmatrix} dp[k-1][j],dp[k-1][j-v[i]]+w[i]| \in group k\end{Bmatrix}

小結

分組的揹包問題將彼此互斥的若干物品稱為一個組,這建立了一個很好的模型。不 少揹包問題的變形都可以轉化為分組的揹包問題,由分組的揹包問題進一步可 定義“泛化物品”的概念,十分有利於解題。

(來源:揹包九講)

有依賴的揹包問題(重要)

這種揹包問題的物品間存在某種“依賴”的關係。也就是說,物品 i 依賴於物品 j, 表示若選物品 i,則必須選物品 j。為了簡化起見,我們先設沒有某個物品既依賴於別 的物品,又被別的物品所依賴;另外,沒有某件物品同時依賴多件物品。(否則就是樹型dp)

分析

有依賴的揹包問題來源於一道非常經典的題:金明的預算

但是這道題其實也有“巧”法 認真題的小朋友們會看到這樣一句話:每個主件可以有 0個1 個或 2個附件

然後對於每一組物品(主件+附件)就有一下5種情況:

  1. 什麼都不選
  2. 只選主件
  3. 主件+附件1
  4. 主件+附件2
  5. 主件+附件1+附件2

依次轉移即可(定義dp[k][j] k表示前k組物品)

即使是上面的“巧”法,我們也用到了之前的分組揹包的思想,如果不這麼定義,狀態將會很難表示,而且無法轉移

現在考慮多個附件的情況

無疑,這樣的策略是非常的,但是每一種策略都是互斥的(即不能同時選取多種策略)

我們可以對問題向分組揹包進行如下轉化:一個主件和它的附件集合對應分組揹包中的一個物品組,每個選擇了主件又選擇了若干個附件的策略對應於這個物品組中的一個物品,其費用和價值都是這個策略中的物品的值的和

然而僅僅考慮到這一點是不夠的,因為每一個物品組的物品數量十分地多(選了主件之後,每種附件可以選或不選,也可以直接就不選主件,所以物品數量等於決策數量,為\large 2^{n}+1),在資料過大的時候,時間會難以承受。

接下來,我們考慮優化。

對於第 k 個物品組中的 物品,所有費用相同的物品只留一個價值最大的,不影響結果。

所以,可以對主件 k 的 “附件集合”先進行一次 01 揹包,得到費用依次為 0. . .V-Ck 所有這些值時相應的最大價值 f[0 . . . V-Ck]。

就相當於,我們把原來的那麼多附件的物品的組合變成了V-Ck件重量分別為0. . .V-Ck,價值為f[0 . . . V-Ck]的物品,從而極大地減少了物品組中物品的數量。

然後,就可以優雅地用分組揹包解決這個問題了。

或者我後面想到了另一種理解的思路

就是假設我們先選“主件”,然後選了主件之後附件就可以隨便選,就用0-1揹包做一下,然後就可以求出選了這個主件的最大價值

然後再一次更新,看這個物品組選不選(考慮連“主件”都不買的情況)

舉一道例題

emmm...其實第一種思路是理解的揹包九講裡面的東西 但是我沒有打過這種思路的程式碼 不上手的話 其實還有點迷

如果有什麼BUG的話,歡迎指正 悄悄溜走~~~

最後是非常不正經的ending

參考了《揹包九講》和網上一些資料,會在博文中標註,大多數部分為原創,請放心食用;由於作者水平有限,若有理解不到位或者表達有什麼紕漏,可以 call me at [email protected] 或加qq請註明必要的資訊+csdn

相關推薦

揹包問題優雅總結費用+分組+依賴

目錄 作者有話說 小結 小結 分析 作者有話說 本篇博文中的各類陣列都從1開始 題目裡好像混進去了什麼奇怪的東西 二維費用的揹包問題 二維費用的揹包問題是指:對於每件物品,具有兩種不同的費用,選擇這件物品必須同時付出這兩種費用

DP專題:DP初步』

<更新提示> <第一次更新> <正文> 二維動態規劃 初步 二維動態規劃並不是指動態規劃的狀態是二維的,而是指線性動態規劃的拓展,由線性變為了平面,即在一個平面上做動態規劃。 例題 馬攔過河卒 題目描述

HDU2159 FATE費用揹包+完全揹包

FATE Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 19336  &

費用的01揹包 HDU3496 HDU2184

HDU3496     已空間優化     疑惑點在 dp[時間][看電影數量]的初始化問題上面     dp[0][0]=0。。。。是吧     dp[0][i]=-inf,,,,,,,這個-inf一

POJ1195 Mobile phones 樹狀數組

chan mono ins written writing ram cor data- amp Mobile phones Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 1428

樹狀數組See you~

get iostream closed href typedef 線段樹 比較 space 線段 https://www.bnuoj.com/v3/contest_show.php?cid=9148#problem/F 【題意】 給定一個矩陣,每個格子的初始值為1。現在可以

BZOJ4785 [Zjoi2017]樹狀數組 線段樹 + 標記永久化

結合 題解 php 數組 air line pri www ostream 題目鏈接 BZOJ4785 題解 肝了一個下午QAQ沒寫過二維線段樹還是很難受 首先題目中的樹狀數組實際維護的是後綴和,這一點憑分析或經驗或手模觀察可以得出 在\(\mod 2\)意義下,我們實際求

Oracle表管理:約束

value light 成功 字段 註意 ont sed 刪除外鍵 img 1、簡單的表創建和字段類型最簡單的方式去創建表(沒有添加主鍵之類的約束條件)【Oracle的字段類型】number:數值類型--整數類型:number(a) 總長度a--小數類型:number(a,

樹狀數組CF10D LCIS

chan wap 傳送門 樹狀 lcis tdi swa long long code 傳送門 Description 給你兩個串,求他們的最長公共上升子序列 Input 第一行是第一個串的長度\(n\) 第二行\(n\)個數代表第一個串 第三行是第二個串的長度\(m\)

Counting Black POJ - 1656線段樹+記憶體優化

題目連結   這道題卡了記憶體,但是處理這個記憶體的方式卻也簡單,可以直接用short int來減少記憶體的使用,於是就可以用四叉樹——二維線段樹過了。 #include <iostream> #include <cstdio> #include &

Matrix POJ - 2155線段樹+永久化標記

題目連結   挺好的一道題,一開始用lazy標記往下推,總是推不出樣例的正解,然後就去看了相關部落格,發現卻確實如此,在這裡是無法用lazy標記來層層推的,並且還會出現超記憶體的情況,所以,便改用了永久化標記來解這道題。   還有一件是,關於discuss裡的討論區有

Java面試系列之:哥們,那你說說系統架構引入訊息中介軟體什麼缺點?

歡迎關注個人公眾號:石杉的架構筆記(ID:shishan100) 週一至週五早8點半!精品技術文章準時送上! 一、前情回顧 上篇文章「Java進階面試系列之一」你們系統架構中為何要引入訊息中介軟體?,給大家講了講訊息中介軟體引入系統架構的作用,主要是解決哪些問題的。 其比較常見的實踐場景是: 複雜系統

HDU 2159 FATE揹包+完全揹包

source: 題意:現在玩遊戲欲升級,升級需要經驗值n,殺怪可以賺經驗值,但是會扣忍耐度,遊戲中有k種怪,數目都無限多。現在玩家還有m點忍耐度,問能否在最多殺s個怪的情況下升級,若能則輸出剩餘

TOJ 3596. Watch The Movie基礎的費用揹包問題

           昨天訓練賽有一道二維費用揹包的題,結果我守著揹包九講在手邊就是沒做出來。事後發現其實解法揹包九講都已經講到了,只不過自己看的不仔細罷了。以後看解題報告也好,論文也好,一定要深入思考一下,真正將這個問題搞懂並且做到可以拓展,那才是真正的學懂了。      

shell腳本高級總結

shell腳本 經過一周腳本的折磨,覺得還是有一定的收獲,所以就把一些不容易理解的並且容易忘記的難點做一個總結。shell腳本中主要有兩大模塊,第一就是流程控制的腳本,第二就是函數控制的腳本。▲首先,流程控制包括順序執行,選擇執行,循環執行。主要的條件語句就是if。那就來先說說if語句吧!1.if語句分為單

JavaScript的之路()函數簡介,變量、作用域和內存問題

ret 優化 person get 簡介 web瀏覽器 都是 add 是把 <h3>ECMAScript中函數不存在函數簽名的概念,沒有重載</h3><h3>無需指定返回值,可以在任何時候返回任何值。未指定返回值的函數,返回的是一個特殊

HDU 5517 樹狀數組///三偏序問題

void blog scan memset 集合 while ++ struct name 題目鏈接:【http://acm.split.hdu.edu.cn/showproblem.php?pid=5517】 題意:定義multi_set A<a , d>,B

BZOJ1513 [POI2006]Tet-Tetris 3D 線段樹

get mem HR void 修改 mod 3D 理解 fine 題目鏈接 BZOJ1513 題解 真正地理解了一波線段樹標記永久化的姿勢 每個節點維護兩個值\(v\)和\(tag\) \(v\)代表兒子中的最值 \(tag\)代表未下傳的最值 顯然節點的區間大於等於\(

碼QRious 介紹

二維碼又稱QR Code,QR全稱Quick Response,是一個近幾年來移動裝置上超流行的一種編碼方式,它比傳統的Bar Code條形碼能存更多的資訊,也能表示更多的資料型別。   二維條碼/二維碼(2-dimensional bar code)是用某種特定的幾何圖形按一定規律在平面(二維

Check Corners HDU - 2888線段樹

題目連結   很多人寫這道題都用的是二維RMQ,但是,我覺得這道題可以鍛鍊一下我二維線段樹的思維,但是,無獨有偶,這道題會卡一些二維線段樹的模板,一開始我想也沒想,直接敲了剛學的線段樹,然後不停的RE,後來改了下,換成單點更新與區間更新二維線段樹,還是不行TLE了,於是,就開始想,