题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=3449

题目大意:

fj打算去买一些东西,在那之前,他需要一些盒子去装他打算要买的不同的物品。每一个盒子有特定要装的东西(就是说如果他要买这些东西里的一个,他不得不先买一个盒子)。每一种物品都有自己的价值,现在FJ只有W元去购物,他打算用这些钱买价值最高的东西。

思路:

这是有依赖的背包,每件物品买之前必须买特定的盒子

背包九讲:

所以先对每一个箱子进行01背包,保存可以凑出的所有的花费和该花费的最大价值,这是一组中的所有状态,且只能取一个或者不取,背包转化成分组背包,然后就可以做了。

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
typedef pair<int, int> Pair ;
const int INF = 0x3f3f3f3f;
const int maxn = 1e5 + ;
int T, n, m, cases;
struct node
{
int price;
int num;
int price_sum;
int cost[], value[];
int dp[];
};
node a[];
int dp[maxn];
int main()
{
while(cin >> n >> m)
{
memset(dp, , sizeof(dp));
memset(a, , sizeof(a));
for(int i = ; i < n; i++)
{
scanf("%d%d", &a[i].price, &a[i].num);
a[i].price_sum = ;
for(int j = ; j < a[i].num; j++)
{
scanf("%d%d", &a[i].cost[j], &a[i].value[j]);
a[i].price_sum += a[i].cost[j];
}
}
for(int i = ; i < n; i++)//对,每个箱子预处理出所有可凑出的花费和该花费的最大价值
{
memset(a[i].dp, -, sizeof(a[i].dp));
a[i].dp[] = ;
for(int j = ; j < a[i].num; j++)
{
for(int k = a[i].price_sum; k >= a[i].cost[j]; k--)
if(a[i].dp[k - a[i].cost[j]] >= )a[i].dp[k] = max(a[i].dp[k], a[i].dp[k - a[i].cost[j]] + a[i].value[j]);
}/*
for(int j = 0; j <= a[i].price_sum; j++)
cout<<a[i].dp[j]<<" ";
cout<<endl;*/
}
for(int i = ; i < n; i++)//枚举每一个的箱子
{
vector<Pair>d;
for(int j = ; j <= a[i].price_sum; j++)//将该箱子的所有状态存下来
{
if(a[i].dp[j] > )
d.push_back(Pair(j + a[i].price, a[i].dp[j]));
}
for(int v = m; v >= ; v--)//枚举花费
{
for(int j = ; j < d.size(); j++)//枚举改组的状态
if(v >= d[j].first)
dp[v] = max(dp[v], dp[v - d[j].first] + d[j].second);
}
}
cout<<dp[m]<<endl;
}
return ;
}

还有一种写法,在dp的时候把预处理和状态转化合并起来,时间复杂度降低了一点

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
typedef pair<int, int> Pair ;
const int INF = 0x3f3f3f3f;
const int maxn = 1e5 + ;
int T, n, m, cases;
int a[];
int dp[][];
struct node
{
int v, w;
};
vector<node>G[];
int main()
{
while(cin >> n >> m)
{
memset(dp, , sizeof(dp));
for(int i = ; i <= n; i++)G[i].clear();
int tot, x, y;
for(int i = ; i <= n; i++)
{
scanf("%d%d", &a[i], &tot);
for(int j = ; j < tot; j++)
{
scanf("%d%d", &x, &y);
G[i].push_back(node{x, y});
}
} for(int i = ; i <= n; i++)//枚举每种箱子
{
for(int j = ; j < a[i]; j++)dp[i][j] = -;
for(int j = a[i]; j <= m; j++)dp[i][j] = dp[i - ][j - a[i]];//这里是确保先购买购物车 for(int j = ; j < G[i].size(); j++)//在购物车内进行01背包
{
for(int k = m; k >= G[i][j].v; k--)
{
if(dp[i][k - G[i][j].v] != -)
dp[i][k] = max(dp[i][k], dp[i][k - G[i][j].v] + G[i][j].w);
}
}
for(int j = ; j <= m; j++)dp[i][j] = max(dp[i - ][j], dp[i][j]);//和之前的值比较
}
cout<<dp[n][m]<<endl;
}
return ;
}

hdu-3449 Consumer---有依赖性质的背包的更多相关文章

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

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

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

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

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

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

  4. HDU 3449 Consumer

    这是一道依赖背包问题.背包问题通常的解法都是由0/1背包拓展过来的,这道也不例外.我最初想到的做法是,由于有依赖关系,先对附件做个DP,得到1-w的附件背包结果f[i]表示i花费得到的最大收益,然后把 ...

  5. HDU 2159 FATE(二维费用背包)

    FATE Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submi ...

  6. HDU 1712 ACboy needs your help(包背包)

    HDU 1712 ACboy needs your help(包背包) pid=1712">http://acm.hdu.edu.cn/showproblem.php? pid=171 ...

  7. 【MVVM Dev】多个具有依赖性质的ComboBox对数据的过滤

    一.前言 在界面编程中,我们常常会遇到具有依赖性质的ComboBox框,比如最常见的: 省/直辖市 => 地级市/区 => 区/街道 今天就说一下在WPF的MVVM模式中如何实现该功能 二 ...

  8. HDOJ(HDU).1284 钱币兑换问题 (DP 完全背包)

    HDOJ(HDU).1284 钱币兑换问题 (DP 完全背包) 题意分析 裸的完全背包问题 代码总览 #include <iostream> #include <cstdio> ...

  9. 洛谷 P1064 金明的预算方案【有依赖的分组背包】

    题目描述 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间.更让他高兴的是,妈妈昨天对他说:"你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过N元钱 ...

随机推荐

  1. delete ELK index

    Go to tab “Dev Tools”4. On the left console type:GET _cat/indices?v&s=store.size:descand execute ...

  2. WEB视频播放器插件,总结

    WEB视频播放器插件,总结 2018年07月29日 20:42:11 流光忆莲 阅读数:572更多 个人分类: 推荐文章收藏   以下是关于网页中嵌入视频播放插件的各种资料的总结 基于H5的Vedio ...

  3. git只clone仓库中指定子目录和指定文件的实现

    ## step :初始化空库 [root@vm_test backup]# mkdir devops [root@vm_test backup]# cd devops/ [root@vm_test d ...

  4. 电脑c盘爆满检查与设置

    C盘文件爆满,先检查是那个文件造成的 操作方法:打开文件夹选项,将“隐藏受保护的操作系统文件(推荐)”前的勾选去掉,然后打开系统盘查看是那个文件占用空间大 Hiberfil.sys文件删除方法: 1. ...

  5. 转 Comparison of Red Hat and Oracle Linux kernel versions and release strings

    Originally derived from Red Hat Enterprise Linux (RHEL), Oracle Linux (OL) contains minor difference ...

  6. html-3

    <hr> 下划线实体:想在页面显示被浏览器解析的内容为表格添加标题<caption>跟tr同级,只在<table>下 <link> 为页面加小图标 在& ...

  7. Google Zxing 生成二维码

    Net Zxing 源码地址 http://zxingnet.codeplex.com/ github 地址 https://github.com/zxing/zxing 新建一个Winform 项目 ...

  8. [转]js 判断图片存在

    转自:http://blog.csdn.net/qq415734794/article/details/7261479 .//检查图片是否存在 .function CheckImgExists(img ...

  9. Android平台网络常用命令

    工作中经常用到的一些命令,整理一下,方便以后进行参考 1.IP设置 ifconfig eth0 128.224.156.81 up  //一般的嵌入式linux中设置IP.ifconfig eth0 ...

  10. 读<<programming ruby>> 7.6节 flip-flop 理解

    书中源码是这样的 File.foreach('1.txt') do |x| if(($. == 1) || x =~ /eig/) .. (($. == 3) || x =~ /nin/) then ...