题目链接:

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. Go语言基础之6--值类型和引用类型

    一. 引用类型 引用类型理解为(C语言):指针 Golang中只有三种引用类型:slice(切片).map(字典).channel(管道): 实例1-1 package main import &qu ...

  2. Idea如何设置代码超出长度限制时自动换行

    在[File]-->[Settings]-->[Code Sytle]中勾选[Wrap on typing]选项

  3. Ubuntu14.10:Install Apache,PHP,Mysql以及扩展库

    step 1: Apache sudo apt-get install apache2 After have apache2 installed, go to localhost by browser ...

  4. arraylist和linkedlist内部的实现大致是怎样的

    1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构. 2.对于随机访问get和set,ArrayList优于LinkedList,因为ArrayList可以随 ...

  5. thinkphp自动验证和自动完成

    tp验证码的自动验证小案例 模板文件 <form action="" method="post"> <p> User: <inpu ...

  6. Vue循环中多个input绑定指定v-model

    Vue.js中提供了v-model可以双向绑定表单元素,这个方法可以非常方便的获得输入的值,但是有时候表单元素需要循环生成,在循环中要怎样获得指定输入框的值呢 这里介绍两种,一种是v-for中循环生成 ...

  7. css 断行省略号,隐藏,fixed定位

    text-overflow(clip | elipsis)(显示省略号| 不显示省略号) white-space:nowrap    强制文字不断行 word-break:break-all;     ...

  8. 使用springmvc时处理404的方法

    使用springmvc时处理404的方法 来源: https://www.cnblogs.com/handsome-man/p/5519439.html,再次申明不是我原创的,尊重原创 如何定义404 ...

  9. java字符串转Date

    public static Date StrToDate(String str) { SimpleDateFormat format = new SimpleDateFormat("yyyy ...

  10. speex编译

    首先去官网 https://www.speex.org/downloads/ 下载解压 将include.libspeex文件夹复制到自己新建工程的jni目录下 speex有关的类 package c ...