hdu-2602 Bone Collector(dp)
阿新 • • 發佈:2018-12-28
題目:http://acm.hdu.edu.cn/showproblem.php?pid=2602
題意:給出n個物體和揹包重量m,之後兩行給出n個物體的價值和相對應的重量,求出最多可以裝多少價值的物體。(01揹包裸題)。
dp思路:01揹包的板子題,每個物體思考拿或不拿,二維的做法為
for (int i = 1; i <= n; i++){ for (int j = w[i]; j<=m; j++){ dp[i][j] = max(dp[i-1][j], dp[i-1][j - w[i]] + v[i]); } }
dp[i][j]為第i個物體在揹包上限為j時拿或不拿所能達到的最大收益。選擇不拿時dp[i][j]=dp[i-1][j],該狀態的收益即為第i-1件物品在揹包上限為j時的最大收益;選擇拿時,dp[i][j]=dp[i-1][j-w[i]]+v[i],該狀態為第i-1件物品在揹包上限為j-w[i]時的最大收益加上第i件物品的價值。
一維的優化做法為:
for (int i = 1; i <= n; i++){ for (int j = m; j >= w[i]; j--){ dp[j] = max(dp[j], dp[j - w[i]] + v[i]); } }
和二維有所不同的時內部的迴圈需要從後往前,原因為:一維的做法的可行性是由於每次判斷第i件物品的拿或不拿時只需要第i-1行的狀態,那麼將其優化成一行每次對應改變即可,從前往後會提前更改前面的狀態,從第i-1件物品變為了第i件物品,此時後面的更新就會用到已經更新的資料,從而出現錯誤。
#include <iostream> #include <cstdio> #include <cstdlib> #include <vector> #include <cstring> #include <set> #include <algorithm> #include <queue> using namespace std; typedef long long ll; int dp[1100]; int w[1100]; int v[1100]; int main(){ int t; scanf("%d", &t); while (t--){ int m, n; scanf("%d%d", &n, &m); memset(dp, 0, sizeof(dp)); for (int i = 1; i <= n; i++) cin >> v[i]; for (int i = 1; i <= n; i++) cin >> w[i]; for (int i = 1; i <= n; i++){ for (int j = m; j >= w[i]; j--){ dp[j] = max(dp[j], dp[j - w[i]] + v[i]); } } cout << dp[m] << endl; } //system("pause") }