1. 程式人生 > >hdu-2602 Bone Collector(dp)

hdu-2602 Bone Collector(dp)

題目: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")
}