HDOJ 3535 AreYouBusy (分情况的分组背包)
2014-03-04 19:31
274 查看
题意:n 组,每组有 m 个物品,每一组的属性为 0 或 1 或 2 。
0 代表该组中至少取一个,1 代表至多取一个,2 代表没有限制。
cost[i][j] hap[i][j] 存第 i 组第 j 个物品的花费和价值。
令 dp[i][j] 表示前 i 组,花费不超过 j 时的最大价值。
dp[i][j] 转移: a: dp[i-1][j-cost[i][j]] + hap[i][j] ,表示取完前 i-1 组后,取第 i 组的第 j 个物品。
b: dp[i][j-cost[i][j]] + hap[i][j] ,表示取完第 i 组某个物品,继续取第 i 组第 j 个物品。
显然,属性为 0、2 时,a 和 b 均为转移,属性为 1 时,转移只有 a。
初始化:按照背包9讲,这里为不许要恰好装满背包的情况,因此 dp[i][j] 应初始化为 0。因为至少背包里什么都不装的话应该价值为 0。
但是,对于属性 0,由于有要求说至少装一个,所以什么都不装是不合法的情况,因此应初始化为负无穷。
循环的次序问题:
我刚开始把循环的部分一律写成了:
for(int v = t; v >= 0; v--) {
for(int j = 0; j < m; j++) {
if(v - cost[i][j] >= 0) {这种显然是不对的,因为按照这样有可能出现同一物品取多次的情况。
改成:
for(int j = 0; j < m; j++) {
for(int v = t; v >= 0; v--) {
if(v - cost[i][j] >= 0) {就 AC 了。但是这样为什么是对的呢?
这种循环我觉得(不知道对不对,mark一下)是对 dp[i][j] 不断更新,先考虑 n 中第 1 个物品,计算出一系列 dp[i][j],然后前 2 个,依次类推。最后把所有物品考虑进来。
由于最外层 j 的循环只执行一趟,所以可以保证每个 j 只考虑一次,避免了一个物品取多次。
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 110, inf = 0x3f3f3f3f;
int n, t, cost[maxn][maxn], hap[maxn][maxn];
int dp[maxn][maxn];
int main()
{
while(~scanf("%d%d", &n, &t)) {
memset(dp, 0, sizeof(dp));
for(int i = 1; i <= n; i++) {
int m, s;
scanf("%d%d", &m, &s);
for(int j = 0; j < m; j++) {
scanf("%d%d", &cost[i][j], &hap[i][j]);
}
if(s == 2) {
for(int j = 0; j <= t; j++) {
dp[i][j] = dp[i-1][j];
}
for(int j = 0; j < m; j++) {
for(int v = t; v >= 0; v--) {
if(v - cost[i][j] >= 0) {
dp[i][v] = max(dp[i-1][v], max(dp[i][v], dp[i][v-cost[i][j]] + hap[i][j]));
}
}
}
}
else if(s == 1) {
for(int j = 0; j <= t; j++) {
dp[i][j] = dp[i-1][j];
}
for(int j = 0; j < m; j++) {
for(int v = t; v >= 0; v--) {
if(v - cost[i][j] >= 0) {
dp[i][v] = max(dp[i][v], dp[i-1][v-cost[i][j]] + hap[i][j]);
}
}
}
}
else {
for(int j = 0; j <= t; j++) {
dp[i][j] = -inf;
}
for(int j = 0; j < m; j++) {
for(int v = t; v >= 0; v--) {
if(v - cost[i][j] >= 0) {
dp[i][v] = max(dp[i][v], max(dp[i-1][v-cost[i][j]] + hap[i][j], dp[i][v-cost[i][j]] + hap[i][j]));
}
}
}
}
}
printf("%d\n", dp
[t] >= 0 ? dp
[t] : -1);
}
return 0;
}
相关文章推荐
- hdu 3535 AreYouBusy(经典分组背包)
- hdu 3535 AreYouBusy(分组背包)(推荐)
- hdu 3535 AreYouBusy 分组背包
- HDU 3535 AreYouBusy(混合背包与分组背包)
- hdu 3535 AreYouBusy[各种分组背包]
- HDU 3535 AreYouBusy(混合背包+分组背包/至少取一件)
- HDU 3535 AreYouBusy(分组背包)
- hdu 3535 AreYouBusy(分组背包的变形---各种分组背包)
- hdu 3535 Are You Busy 分组背包,组内至少放一个和组内至多放一个
- hdoj 3535 AreYouBusy(混合背包)
- hdu 3535 AreYouBusy(分组背包->总和考察)
- HDU 3535:AreYouBusy(分组背包)
- hdu 3535 AreYouBusy(各种分组背包)
- hdu 3535 AreYouBusy(混合分组背包)
- HDOJ 3535 AreYouBusy (背包 每组至少一个)
- [HDU 3535] AreYouBusy (动态规划 混合背包 值得做很多遍)
- HDU 3535 AreYouBusy -- 分了组的混合背包
- HDU - 3535 AreYouBusy(混合背包)
- 第四讲 混合三种背包问题 HDU 3535 AreYouBusy
- HDU-3535 AreYouBusy(多组背包)