現在我們有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 行,每行兩個整數 ...