CF816E-Karen and Supermarket
题目
Description
今天Karen要去买东西。
一共有 \(n\) 件物品,每件物品的价格为\(c_i\),同时每件物品都有一张优惠券,可以对这件物品减价 \(d_i\) . 使用第 \(i\) 件物品的优惠券的条件是买这件物品并且使用了第 \(x_i\) 张优惠券。现在给出Karen带的钱数 \(b\) ,问最多能买几件物品。
Input
第一行两个整数 \(n\le 5\times 10^3 , b\le 10^9\) 。
接下来 \(n\) 行中第 \(i\) 行,首先有两个整数 \(c_i,d_i\le 10^9\) 。对于 \(i>1\) 有第三个整数 \(1\le x_i<i\) 。
Output
一行,输出最多能买的物品个数。
Sample Input
样例1:
6 16
10 9
10 5 1
12 2 1
20 18 3
10 2 3
2 1 5
样例2:
5 10
3 1
3 1 1
3 1 2
3 1 3
3 1 4
Sample Output
样例1:
4
样例2:
5
Hint
样例1: 买1,3,4号物品,用优惠券;买6号物品,不用优惠券
样例2:买所有的的物品,用优惠券
分析
由于每个物品只有一件,我们可以把问题转化成求买 \(k\) 个物品至少需要多少钱,最后再统计最多可以买多少个。
由于有 \(1\le x_i<i\) ,所以优惠券的使用条件构成了一棵树。现在问题是如何在这颗树上求解。
注意到如果一个点不用优惠券,那么子树中所有点都不能用,所以设状态:
\(f[x][i][0,1]\) 表示以 \(x\) 为根的子树中买 \(i\) 件物品,是否可以用优惠券(0不能,1能),那么可以通过子树的信息来更新当前点:
f[x][i+j][1]=\min \{f[u][i][1]+f[v][j][1],f[u][i][0]+f[v][j][1],u,v\in \text{subtree}(x)\} \\
\]
即如果当前点不可用优惠券,那么子树都不能用。如果当前点用优惠券,那么子树可用可不用。
这样\(f[\text{root}][k][1]\)就是我们要求的东西。
这样做似乎是\(O(n^3)\)的呢!我们实际上是枚举子树中的点对,所以可以不断地把点合并进当前点中,就可以做到\(n^2\)级别了。
循环的时候要从后往前,否则无法保证每件物品只买一次。
代码
#include<cstdio>
#include<cctype>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long giant;
int read() {
int x=0,f=1;
char c=getchar();
for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
for (;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
const int maxn=5e3+10;
const giant inf=1e13;
int n,bud;
giant f[maxn][maxn][2];
vector<int> g[maxn];
void add(int x,int y) {g[x].push_back(y);}
void Min(giant &x,giant y) {x=min(x,y);}
int dfs(int x) {
int sz=1;
for (int v:g[x]) {
int vs=dfs(v);
for (int j=sz;j>=0;--j) {
for (int i=vs;i>=0;--i) {
Min(f[x][i+j][0],f[x][j][0]+f[v][i][0]);
Min(f[x][i+j][1],f[x][j][1]+f[v][i][1]);
}
}
sz+=vs;
}
for (int i=0;i<=n;++i) Min(f[x][i][1],f[x][i][0]);
return sz;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
#endif
n=read(),bud=read();
for (int i=1;i<=n;++i) for (int j=0;j<=n;++j) for (int k=0;k<2;++k) f[i][j][k]=inf;
for (int i=1;i<=n;++i) {
f[i][0][0]=0,f[i][1][0]=read(),f[i][1][1]=f[i][1][0]-read();
if (i>1) add(read(),i);
}
dfs(1);
int ans=0;
for (int i=1;i<=n;++i) if (f[1][i][1]<=bud) ans=i;
printf("%d\n",ans);
return 0;
}
CF816E-Karen and Supermarket的更多相关文章
- [CF816E] Karen and Supermarket1 [树形dp]
传送门 - > \(CF816E\) Karen and Supermarket 题意翻译 在回家的路上,凯伦决定到超市停下来买一些杂货. 她需要买很多东西,但因为她是学生,所以她的预算仍然很有 ...
- Codeforces 815C Karen and Supermarket 树形dp
Karen and Supermarket 感觉就是很普通的树形dp. dp[ i ][ 0 ][ u ]表示在 i 这棵子树中选择 u 个且 i 不用优惠券的最小花费. dp[ i ][ 1 ][ ...
- CF815C Karen and Supermarket
题目链接 CF815C Karen and Supermarket 题解 只要在最大化数量的前提下,最小化花费就好了 这个数量枚举ok, dp[i][j][1/0]表示节点i的子树中买了j件商品 i ...
- CF815C Karen and Supermarket [树形DP]
题目传送门 Karen and Supermarket On the way home, Karen decided to stop by the supermarket to buy some gr ...
- E. Karen and Supermarket
E. Karen and Supermarket time limit per test 2 seconds memory limit per test 512 megabytes input sta ...
- Codeforces Round #419 (Div. 1) C. Karen and Supermarket 树形DP
C. Karen and Supermarket On the way home, Karen decided to stop by the supermarket to buy some g ...
- codeforces 815C Karen and Supermarket
On the way home, Karen decided to stop by the supermarket to buy some groceries. She needs to buy a ...
- codeforces round #419 E. Karen and Supermarket
On the way home, Karen decided to stop by the supermarket to buy some groceries. She needs to buy a ...
- Codeforces 815 C Karen and Supermarket
On the way home, Karen decided to stop by the supermarket to buy some groceries. She needs to buy a ...
- 【Codeforces 815C】Karen and Supermarket
Codeforces 815 C 考虑树型dp. \(dp[i][0/1][k]\)表示现在在第i个节点, 父亲节点有没有选用优惠, 这个子树中买k个节点所需要花的最小代价. 然后转移的时候枚举i的一 ...
随机推荐
- 20155308 实验四 Android开发基础
20155308 实验四 Android开发基础 实验内容 基于Android Studio开发简单的Android应用并部署测试; 了解Android.组件.布局管理器的使用: 掌握Android中 ...
- 20155322 2016-2017-2 《Java程序设计》实验二《Java面向对象程序设计》
20155322 2016-2017-2 <Java程序设计>实验二<Java面向对象程序设计> 实验目的与内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承 ...
- 20155322 2016-2017-2 《Java程序设计》实验一 Java开发环境的熟悉(macOS + Eclipse)
20155322 2016-2017-2 <Java程序设计>实验一 Java开发环境的熟悉(macOS + Eclipse) 实验目的与内容 熟悉命令行开发环境. 使用vim等文本编译器 ...
- 安装虚拟机和Linux系统的学习
安装虚拟机和Linux系统的学习(随笔3) 1.安装虚拟机 首先我按着老师给的链接上的步骤一步一步安装VirtualBox,进行得十分顺利. 接着则是在虚拟机上安装Ubuntu. 然而安装完成以后按要 ...
- 20155330 实验三 敏捷开发与XP实践
20155330 实验三 敏捷开发与XP实践 实验内容 XP基础 XP核心实践 相关工具 实验步骤 (一)敏捷开发与XP 软件工程是把系统的.有序的.可量化的方法应用到软件的开发.运营和维护上的过程. ...
- Apache入门篇(四)之LAMP架构部署
一.LAMP解析 a: apachem: mariadb, mysqlp: php, perl, python 静态资源:静态内容:客户端从服务器获得的资源的表现形式与原文件相同:动态资源:通常是程序 ...
- MSP430编译器__intrinsic指令
1. 在文件intrinsics.c里面发现很多函数前面有__intrinsic,说是这些是MSP430的特定函数(其他单片机用不了),应该和编译器有关,并没有具体的函数实现,我猜测,是直接转成汇编代 ...
- eclipse jetty debug
一. 1, Eeclipse中选择 Run --> External Tools --> External Tools Configurations 然后new一个Program项. ...
- git分支在团队中的使用
须知 在介绍分支常用操作之前 我们需要知道几点: 1.主干不允许做任何修改结构或者业务的操作. 有两种情况可以修改主干: 就是当前主干已经是有问题的,合并后出问题发布不了. 修改与业务无关的配置文件, ...
- Wince 中访问WCF服务
由于本文并非WinCE开发普及篇,所以一些WinCE开发和WCF开发的基础还请移步百度和谷歌寻找答案,然后结合本文开发出WinCE中如何访问WCF,谢谢. 开发环境 IDE:Visual Studio ...