揹包dp之01揹包

2021-09-12 18:00:44 字數 2017 閱讀 9065

現在我們有n個配件,他們有不同的價值.

但是我們揹包的容量是有限的,因為我們只有乙個一級包,

所以我們最多可以裝v重量的東西.

但是為了能更好的吃到雞(不存在的)我們要攜帶更有價值的配件,請問我們最多能拿多少價值的配件來當快遞員呢??

輸入的第一行是t,

表示有一共要打t場比賽.

每組資料由三行組成.

第一行包含兩個整數n和v(n <= 1000, v <= 1000).

n表示配件的個數,

v表示一級包的大小(系統會更新嘛).

第二行包含n個整數,

表示每乙個配件的價值.

第三行包含n個整數,

表示每個配件的重量.

最基礎的01揹包問題。

我們首先要建乙個二維dp陣列;

第一維表示第i個配件(1–n),第二維表示揹包的大小(1–v)。

dp[i][j]:表示從第乙個物件取到第i個物件,當揹包大小為j時的所能拿到的最大值。

那麼,再向下一步轉換,得到狀態轉移方程

dp[ i ][ j + 1 ] = max(dp[ i - 1 ][ j - w[ i ] ] + v[ i ],dp[ i - 1 ][ j ])

其意思就是在拿第i個物件(dp[ i - 1 ][ j - w[ i ] ])和不拿第i個物件(dp[ i - 1 ][ j ])之間做選擇。

找出了上面那條狀態轉移方程,題目就很簡單了。

兩層for迴圈:

1:1—>n

2:1—>v

可以看到,如果按照思路來做的話,我們需要的空間為n*v;

當n或者v過大時,我們期望可以減小它的空間複雜度,那麼就有了下面這個只需要空間為n大小的做法。

當我們完成第i-1層的迴圈,到達第i層的迴圈

觀察我們的dp陣列可以發現:

1:我們第i層是由i-1層轉化過來的,而且第i層是按順序推的。

2:dp陣列的第i層的元素之間沒有關係,因為他們都是由上一層推過來的

所以對於第i層,也就是說我們可以任意順序來推,而且不影響它的值,比如第i層,我可以先求dp[i][4],再求dp[i][1],再求dp[i][5],是完全可以的。

既然如此,我們能不能只利用一層來迴圈呢?

我們發現dp[i][j]只和dp[i-1][k]( k < j )有關!也就是對於第j個,只與它前面的有關,和後面的無關!再結合我們剛才得到的結論:dp陣列的第i層的元素之間沒有關係,我們可以任意順序來推

那麼我們就可以從後面來推,從陣列後面逐個更新( j 的迴圈順序 v—>0)!就避免了會因修改陣列元素出現錯誤的情況了!

得到狀態轉移方程

dp[i] = max( dp[ i - w[i] ]+ v[i] ,dp[i])(這裡的dp[i] (粗體)就是原來上一層的dp[ i-1 ][ j ])

**如下:

#include

#include

#include

#include

#include

#include

#include

#include

using namespace std;

#define max 1100

int n,w;

int w[max]

,v[max]

;int dp[max]

;int

big(

int a,

int b)

void

solve

(void

)sort

(dp,dp+w)

;printf

("%d\n"

,dp[w]);

}int

main()

return0;

}

揹包dp之01揹包變形

一種雙核cpu的兩個核能夠同時的處理任務,現在有n個已知資料量的任務需要交給cpu處理,假設已知cpu的每個核1秒可以處理1kb,每個核同時只能處理一項任務。n個任務可以按照任意順序放入cpu進行處理,現在需要設計乙個方案讓cpu處理完這批任務所需的時間最少,求這個最小的時間。輸入描述 輸入包括兩行...

DP 揹包九講之01揹包

有n件物品和乙個容量為v 的揹包。放入第i件物品耗費的空間是ci,得到 的價值是wi。求解將哪些物品裝入揹包可使價值總和最大。這是最基礎的揹包問題,特點是 每種物品僅有一件,可以選擇放或不 放。用子問題定義狀態 即f i,v 表示前i件物品恰放入乙個容量為v的揹包可以 獲得的最大價值。則其狀態轉移方...

DP 揹包九講之01揹包

有 n 件物品和乙個容量是 v 的揹包。每件物品只能使用一次。第 i 件物品的體積是 vi,價值是 wi。求解將哪些物品裝入揹包,可使這些物品的總體積不超過揹包容量,且總價值最大。輸出最大價值。輸入格式 第一行兩個整數,n,v,用空格隔開,分別表示物品數量和揹包容積。接下來有 n 行,每行兩個整數 ...