[HDU3535] [2010多校聯考10] AreYouBusy [分組揹包][01揹包]
阿新 • • 發佈:2018-11-03
三種物品集合,第一種至少選一個,第二種至多選一個,第三種隨便選。
第三種不帶約束的很簡單,01 揹包就可以了。
其它兩種分別是兩類分組揹包。
需要注意的是ci, gi≥0。注意為0的情況,不要重複計算。
三個子問題都是經典的,尤其是兩個分組揹包如果沒有做過應該瞭解一下。
其中有兩個子問題如果單獨考慮是可以滾動的。
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
int n,T;
int m[105], s[105];
int c[105][105], g[105][105];
int F[105][105];
int main() {
while (~scanf("%d%d", &n, &T)) {
for (int i = 1; i <= n; ++i) {
scanf("%d%d", &m[i], &s[i]);
for (int j = 1; j <= m[i]; ++j) {
scanf("%d%d", &c[i][j], &g[i][j]);
}
}
memset(F, 0, sizeof(F));
for (int i = 1; i <= n; ++i) {
if (s[i] == 0) memset(F[i], 0xcf, sizeof(F[i]));
else memcpy(F[i], F[i-1], sizeof(F[i-1]));
for (int k = 1; k <= m[i]; ++k) {
for (int j = T; j >= 0; --j) {
if (j < c[i][k]) continue;
if (s[i] == 0) {
F[i][j] = max(F[i][j], F[i][j-c[i][k]] + g[i][k]);
F[i][j] = max(F[i][j], F[i-1][j-c[i][k]] + g[i][k]);
}
else {
if (s[i] == 1) F[i][j] = max(F[i][j], F[i-1][j-c[i][k]] + g[i][k]);
if (s[i] == 2) F[i][j] = max(F[i][j], F[i][j-c[i][k]] + g[i][k]);
}
}
}
}
printf( "%d\n", max(F[n][T],-1) );
}
return 0;
} }
}
}
printf( "%d\n", max(F[n][T],-1) );
}
return 0;
}