这是一道依赖背包问题。
背包问题通常的解法都是由0/1背包拓展过来的,这道也不例外。
我最初想到的做法是,由于有依赖关系,先对附件做个DP,得到1-w的附件背包结果f[i]表示i花费得到的最大收益,然后把每个f[i]看成花费为i+c[i],收益为f[i]的物品依次做0/1背包。
显然,问题是物品数目过多,复杂度为w*w,无法承受。
同时,此问题的主件收益为0这一点也需要细加考虑,由于主件收益为0,其实际上对每个附件方案的影响只有花费+c[i],这样考虑下来我们只需要对附件进行DP,然后附加上+c[i]的影响即可。

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#include<map>
#include<cstdlib>
using namespace std;
#define ll long long
#define up(i,j,k) for(int i=(j);i<=(k);i++)
#define cmin(a,b) a=min(a,b)
#define cmax(a,b) a=max(a,b)
#define pii pair<int,int>
const int maxn=,inf=1e9,mod=;
int read(){
int ch=getchar(),x=,f=;
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<='')x=(x<<)+(x<<)+ch-'',ch=getchar();
return f*x;
}
int n,w;
int f[maxn],g[maxn],p[],m[];
int c[],v[];
int main(){
freopen("chad.in","r",stdin);
freopen("chad.out","w",stdout);
while(scanf("%d%d",&n,&w)!=EOF){
memset(f,,sizeof(f));
memset(g,,sizeof(g));
up(i,,n){
scanf("%d%d",&p[i],&m[i]);
up(j,,m[i]){
scanf("%d%d",&c[j],&v[j]);
for(int k=w;k>=c[j];k--)
g[k]=max(g[k-c[j]]+v[j],g[k]);
}
up(j,p[i],w)f[j]=max(f[j],g[j-p[i]]);
memcpy(g,f,sizeof(f));
} printf("%d\n",f[w]);
}
return ;
}

事实上,第一种方法也是可行的,只不过,需要先对g数组进行一个(小优化)。

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#include<map>
#include<cstdlib>
using namespace std;
#define ll long long
#define up(i,j,k) for(int i=(j);i<=(k);i++)
#define cmin(a,b) a=min(a,b)
#define cmax(a,b) a=max(a,b)
#define pii pair<int,int>
const int maxn=,inf=1e9,mod=;
int read(){
int ch=getchar(),x=,f=;
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<='')x=(x<<)+(x<<)+ch-'',ch=getchar();
return f*x;
}
int n,w;
int f[maxn],g[maxn],p[],m[];
int c[],v[],head,q[maxn];
int main(){
freopen("chad.in","r",stdin);
freopen("chad.out","w",stdout);
while(scanf("%d%d",&n,&w)!=EOF){
memset(f,,sizeof(f));
memset(g,,sizeof(g));
up(i,,n){
scanf("%d%d",&p[i],&m[i]);
memset(g,,sizeof(g));
up(j,,m[i])scanf("%d%d",&c[j],&v[j]);
up(j,,m[i])for(int k=w;k>=c[j];k--)
g[k]=max(g[k-c[j]]+v[j],g[k]);
head=;
for(int j=;j<=w;j++)
if(!j||g[j]!=g[j-])q[++head]=j;
for(int j=w;j>=p[i];j--){
for(int k=;q[k]+p[i]<=j&&k<=head;k++)
f[j]=max(f[j],f[j-p[i]-q[k]]+g[q[k]]);
}
}
printf("%d\n",f[w]);
}
return ;
}

HDU 3449 Consumer的更多相关文章

  1. hdu 3449 Consumer (依赖01背包)

    题目: 链接:pid=3449">点击打开链接 题意: 思路: dp[i][j]表示前i个箱子装j钱的材料可以得到的最大价值. 代码: #include<iostream> ...

  2. HDU 3449 Consumer (背包问题之有依赖背包)

    题目链接 Problem Description FJ is going to do some shopping, and before that, he needs some boxes to ca ...

  3. HDU 1561&HDU 3449 一类简单依赖背包问题

    HDU 1561.这道是树形DP了,所谓依赖背包,就是选A前必须选B,这样的问题.1561很明显是这样的题了.把0点当成ROOT就好,然后选子节点前必须先选根,所以初始化数组每一行为该根点的值.由于多 ...

  4. HDu 3449 (有依赖的01背包) Consumer

    题意: 有n件物品,对应有不同的价格和价值,这是典型的01背包.但现在有了一个限制,要买物品先买能装这件物品的特定的盒子,盒子的价值为0 代码理解得还不是太好,感觉这是一个“二重”的01背包.首先假设 ...

  5. hdu 3449 有依赖性的01背包

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=3449  Consumer Description FJ is going to do so ...

  6. hdu 3449

    有依赖的背包,转化成01背包来做: #include<iostream> #include<cstdio> #include<cstring> #include&l ...

  7. hdu 3449 (有依赖的01背包)

    依赖背包 事实上,这是一种树形DP,其特点是每个父节点都需要对它的各个儿子的属性进行一次DP以求得自己的相关属性. fj打算去买一些东西,在那之前,他需要一些盒子去装他打算要买的不同的物品.每一个盒子 ...

  8. HDU 3449 依赖背包

    这道题虽然水水的,但是还是成功地给我增加了10多个WA. 最开始拿着题,一看,依赖背包嘛~直接DFS树形DP嗨起来,甚至连内存都没有算一下,3MLE: 然后又仔细看了一下题,没有必要用树形背包来做嘛, ...

  9. 【DP_背包专题】 背包九讲

    这段时间看了<背包九讲>,在HUST VJUDGE上找到了一个题单,挑选了其中16道题集中做了下,选题全部是HDU上的题,大多是简单题.目前做了点小总结,大概提了下每道题的思路重点部分,希 ...

随机推荐

  1. Spring MVC下拉选项(Select)

    以下示例显示如何在使用Spring Web MVC框架的表单中使用下拉选项(Dropdown).首先使用Eclipse IDE来创建一个WEB工程,实现一个让用户可选择自己所在的国家的功能.并按照以下 ...

  2. Spring学习笔记及资源

    极客学院团队出品 Spring 教程  http://wiki.jikexueyuan.com/project/spring/ Spring 提供了以下两种不同类型的容器. 序号 容器 & 描 ...

  3. windows文件打包命令

    copy /Y partition.bin /b + qcsblhd_cfgdata.bin /b + qcsbl.bin /b + oemsbl.bin /b + fat.amss.bin /b + ...

  4. python3----字符串中的字符倒转

    方法一,使用[::-1]: s = 'python' print(s[::-1]) 方法二,使用reverse()方法: n = list(s) n.reverse() print(''.join(n ...

  5. 枚举callback还是返回列表 ?

    一般都会碰到这样的一个问题,A模块需要返回一系列的object或者message,这样一般有两种处理方式: 1,枚举callback typedef (*callback_type)(obj_type ...

  6. 【BZOJ2770】YY的Treap 结论+线段树

    [BZOJ2770]YY的Treap Description 志向远大的YY小朋友在学完快速排序之后决定学习平衡树,左思右想再加上SY的教唆,YY决定学习Treap.友爱教教父SY如砍瓜切菜般教会了Y ...

  7. SharePoint服务器端对象模型 之 访问网站和列表数据(Part 4)

    (四)栏/字段 SharePoint中的字段(中文版中叫做"栏")与传统的数据栏类似,也有不同类型的区别,不过SharePoint中内置的栏类型除了按照数据类型(如数字.日期和时间 ...

  8. c# 如何利用异或运算进行简单加密解密

    利用“^”异或运算对字符串进行加密 原理:按位做“异或”运算是->位值相同得1,不同得0,如下计算 1 ^ 1 = 0 1 ^ 0 = 1 0 ^ 1 = 1 0 ^ 0 = 0 例如: < ...

  9. 利用Google Analytics API实现自己的统计报表

    Google Analytics 简称 GA,功能实在是太强大了,正因如此,导致调研GA API花费了大量的时间,太多的名词需要梳理. 正确的学习步骤是: 首先,找个有权限的账号,登录GA(https ...

  10. VS2012如何显示行号

    Tools-Options-Text Editor-All Languages –General – Display