题目链接:

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. Photoshop入门教程(六):通道

    学习心得:当大部分人听到通道.心里可能会有一种很害怕的感觉,因为“通道”并不像“图层”这样易于理解,望而生畏.”通道“的本质其实是存储图片的信息,把一张图片比作一个为网站,那么通道就是网站的后台,存储 ...

  2. 《高性能mysql》笔记

    组合索引和sql中的顺序有关 单列索引和sql中的顺序无关

  3. POI 读大文件日志

    POI的三个目录 usermodel 包含很多类,方便用户使用,但是占用内存大 eventusermodel 使用xml的SAX事件解析,XSSFReader创建时必须使用OPCPackage,pkg ...

  4. php数组·的方法-数组检索

    /* * //数组检索函数 * */ //array_keys() 获取数组中所有键名 //array_values() 获取数组中所有键名 $arr6=range('a','e'); print_r ...

  5. from表单,图片预览,和表单提交

    <form> <input id="file" class="topsub-file" type="file" name= ...

  6. php rtrim的一个坑,很“二”的问题

    一.背景: 做项目的时候遇到一种情况,商家的营业时间显示的问题,设计图上要求显示成:“星期一,星期二,星期三,星期四,星期五,星期六,星期天” 换句话说,就是营业星期勾哪个就显示哪个,类似下面这样: ...

  7. 自定义element-ui主题

    自定义element主题颜色:主要参考这个文章https://blog.csdn.net/wangcuiling_123/article/details/78513245,再自己做了一遍成功.感谢. ...

  8. [转]JS判断访问设备、客户端操作系统类型

    本文转自:http://www.cnblogs.com/duanguyuan/p/3534470.html 先给出一个实例:判断windows.linux.android 复制以下代码另存为html文 ...

  9. eureka 源码

    本文为eureka学习笔记,错误之处请指正. ----------------------------------------------------------- 1.服务生产者是怎么注册到配置中心 ...

  10. c语言中的隐式函数声明(转)

    本文转自:http://www.jb51.net/article/78212.htm 在c语言里面开来还是要学习c++的编程习惯,使用函数之前一定要声明.不然,即使编译能通过,运行时也可能会出一些莫名 ...