HDU3535 AreYouBusy

多重揹包問題

該題含有三種揹包問題:

1、在本組中,至少拿一件物品的 0 1 揹包問題

2、在本組中,至多拿一件物品的 0 1 揹包問題

3、在本組中的 0 1 揹包問題

1、對於第一種:

由於至少拿一件物品,故初始化 dp[i]dp[i] 爲 負無窮。因爲該 第 i 組,在各種體積下的合法狀態都是未知的,因爲不可以不拿,不能初始化爲 00 ,而求的是最大值,故初始化爲 負無窮。
由於求的是所有組合起來的最大價值,所以狀態肯定與上一組的狀態有關。
以下是關於 至少取一件 的三種轉移情況:

  • 由於每組至少取一件,所以我可以是該組第一次取物品,那麼就與上一組的狀態有關。
    所以有:dp[i1][jw[i]]+v[i]dp[i-1][j-w[i]]+v[i]。

  • 如果這是該組取得第2.3.4…件,即不是第一件的話,那麼狀態由“該組取的第一件”轉化來。
    所以有:dp[i][jw[i]]+v[i]dp[i][j-w[i]]+v[i]。

  • 在該組中,不取這件物品,那麼由於我一定要在本組中至少取一件,則狀態由本組轉移而來。所以有:dp[i][j]dp[i][j]。

2、對於第二種:

dp[i][0]dp[i][0]時,代表前 ii 組,體積爲 00 的情況。由於取至多一件,故可以不取,則dpdp初始化爲 00
而現在這個 00 的意義變化了,它應該是從上一組複製下來的,因爲我們需要的是進行本組的 010 1 揹包的初始狀態。而由於本應初始化爲 00 而非 無窮待定態,所以在本組的基礎上的初始狀態應該是上一組的末狀態。故一開始需要有 dp[i][j]=dp[i1][j]dp[i][j]=dp[i-1][j]。

狀態由上一層轉移:

  • 可以不取,故在上一層的基礎上不取本組的該物品,則有:dp[i1][j]dp[i-1][j]。
  • 在本組中取這個物品,由於只能取一件,故從上一層轉移:dp[i1][jw[i]]+v[i]dp[i-1][j-w[i]]+v[i]。

3、第三種爲普通 010 1 揹包問題,不再贅述。

代碼如下:

#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
int dp[108][108];
int n, t;
int m, s;
struct Bood
{
	int w;
	int val;
}A[10008];
int main()
{
	while (~scanf("%d%d", &n, &t))
	{
		memset(dp, 0, sizeof(dp));
		for (int i = 1; i <= n; i++) {
			scanf("%d%d", &m, &s);
			for (int j = 1; j <= m; j++) {
				scanf("%d%d", &A[j].w, &A[j].val);
			}
			if (s == 0) {
				memset(dp[i], -0x3f, sizeof(dp[i]));
				for (int j = 1; j <= m; j++) {
					for (int k = t; k >= A[j].w; k--) {
						dp[i][k] = max(dp[i - 1][k - A[j].w] + A[j].val, max(dp[i][k], dp[i][k - A[j].w] + A[j].val));
					}
				}
			}
			else if (s == 1) {
				for (int j = 0; j <= t; j++) {
					dp[i][j] = dp[i - 1][j];
				}
				for (int j = 1; j <= m; j++) {
					for (int k = t; k >= A[j].w; k--) {
						dp[i][k] = max(dp[i][k], dp[i - 1][k - A[j].w] + A[j].val);
					}
				}
			}
			else {
				for (int j = 0; j <= t; j++) {
					dp[i][j] = dp[i - 1][j];
				}
				for (int j = 1; j <= m; j++) {
					for (int k = t; k >= A[j].w; k--) {
						dp[i][k] = max(dp[i][k], dp[i][k - A[j].w] + A[j].val);
					}
				}
			}
		}
		printf("%d\n", max(-1,dp[n][t]));
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章