01揹包(給容量增加限制條件) 之 hdu 3466

//  [7/24/2014 Sjm]
/*
模擬一組測試數據:
2 10
5 10 5
3 5 6
1)若先選擇第一組先來:
揹包所用容量: 0  1  2  3  4  5  6  7  8  9  10
  第一遍循環: 0  0  0  0  0  0  0  0  0  0  5
  第二遍循環: 0  0  0  0  0  6  6  6  6  6  6
2)若先選擇第二組先來:
揹包所用容量: 0  1  2  3  4  5  6  7  8  9  10
  第一遍循環: 0  0  0  0  0  6  6  6  6  6  6
  第二遍循環: 0  0  0  0  0  6  6  6  6  6  11
可見選擇物品的順序會影響最後的結果。
再看方程: dp[j] = max(dp[j], dp[j - arr[i].p] + arr[i].v)
結合測試數據發現,只有保證 dp[j - arr[i].p] 最優,才能保證 dp[j] 最優,滿足無後效性。
若想使 dp[j - arr[i].p] 最優,即要保證:
對於任意兩組值:1) p1, q1, v1 和 2) p2, q2, v2
假設先選擇1),則若想滿足無後效性,
那麼 j-arr[2].p >= arr[1].q,且 j-arr[1].p <= arr[2].q (否則可能出現,依賴先選2)計算的值取到更優的解)
由此推得:arr[1].q - arr[1].p <= arr[2].q - arr[2].p,得到如何去決定物品的順序。。。
 
當然如果不想這樣證明,還有另外一種理解方式:
q-p 的差值越小,在每次循環時,與基本的01揹包相比,不更新的值也就越少,也就越接近基本的01揹包,求出的值也就相對越大。
*/
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAX = 505;
int N, M;
int dp[5005];

struct node {
	int p, q, v;
};

node arr[MAX];

bool Cmp(const node &n1, const node &n2) {
	return (n1.q - n1.p < n2.q - n2.p);
}

int Solve() {
	memset(dp, 0, sizeof(dp));
	for (int i = 1; i <= N; ++i) {
		for (int j = M; j >= arr[i].q; --j) {
			dp[j] = max(dp[j], dp[j - arr[i].p] + arr[i].v);
		}
	}
	return dp[M];
}

int main()
{
	//freopen("input.txt", "r", stdin);
	while (~scanf("%d %d", &N, &M)) {
		for (int i = 1; i <= N; ++i) {
			scanf("%d %d %d", &arr[i].p, &arr[i].q, &arr[i].v);
		}
		sort(arr + 1, arr + N + 1, Cmp);
		printf("%d\n", Solve());
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章