题目大意

给定\(n\)一颗树,每个点上有一个物品

每个物品有价格\(c[i]\)

有优惠券,能使价格减少\(d[i]\)

但是使用优惠券的前提时购买该物品,且父亲也使用优惠券

给定钱包余额\(lim\)

求最多能买多少物品

\(n\le 5000, c[i],d[i],lim\le 10^9\)

分析

树上背包

由于价值的数字很大,不能用钱来表示状态,个数表示dp值

只能先计算购买\(k\)个的最少价钱,再判断限制

\(f[x][i][0]\)表示\(x\)这个点不用优惠券,子树中买了\(i\)个物品的最低价钱

\(f[x][i][1]\)表示\(x\)这个点不用优惠券,子树中买了\(i\)个物品的最低价钱

使用子树不断合并到当前点的方法,可以使复杂度变为\(n^2\)

(每个点对在贡献一次\(O(1)\)复杂度后合并到一个状态中,相互不会再产生贡献)

做法

记\(x\)为当前点,\(y\)为该点的儿子

边界条件

f[x][0][0]=0 ,f[x][0][1]=INF

f[x][1][0]=c[i], f[x][1][1]=c[i]-d[i]

合并转移(k=i+j)

f[x][k][0]=f[x][i][0]+f[y][j][0]

f[x][k][1]=f[x][i][1]+min(f[y][j][0],f[y][j][1])

实现时会算重(因为是01背包)

法1:枚举和\(k\),逆着扫\(k\),再枚举i或j中的一个

法2:枚举\(i\),逆着扫\(i\),再枚举\(j\)

solution

#include <cstdio>
#include <cstring>
#include <cctype>
#include <cmath>
#include <algorithm>
#include <cstdlib>
using namespace std;
const int M=5e3+7;
typedef long long LL; inline int rd(){
int x=0;bool f=1;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
for(;isdigit(c);c=getchar()) x=x*10+c-48;
return f?x:-x;
} struct vec{
int g[M],te;
struct edge{
int y,nxt;
edge(int _y=0,int _nxt=0){y=_y,nxt=_nxt;}
}e[M<<1];
vec(){memset(g,0,sizeof g);te=0;}
inline void push(int x,int y){e[++te]=edge(y,g[x]);g[x]=te;}
inline void push2(int x,int y){push(x,y);push(y,x);}
inline int& operator () (int x){return g[x];}
inline edge& operator [] (int x){return e[x];}
}e; int n,sz[M];
LL lim,c[M],d[M];
LL f[M][M][2]; void dfs(int x,int fa){
int i,j,k,p,y;
sz[x]=1;
f[x][0][0]=0;
f[x][1][0]=c[x];
f[x][1][1]=c[x]-d[x]; for(p=e(x);p;p=e[p].nxt)
if((y=e[p].y)!=fa){
dfs(y,x); for(k=sz[x]+sz[y];k>=0;k--)
for(j=0;j<=sz[y];j++) if((i=k-j)<=sz[x]){
f[x][k][0]=min(f[x][k][0],f[x][i][0]+f[y][j][0]);
f[x][k][1]=min(f[x][k][1],min(f[x][i][1]+f[y][j][0],f[x][i][1]+f[y][j][1]));
} sz[x]+=sz[y];
}
} int main(){ int i,x;
n=rd(); lim=rd(); for(i=1;i<=n;i++){
c[i]=rd(), d[i]=rd();
if(i>1) e.push(rd(),i);
} memset(f,0x3f,sizeof f);
dfs(1,0); int ans=0;
for(i=0;i<=n;i++) if(min(f[1][i][0],f[1][i][1])<=lim) ans=i;
printf("%d\n",ans); return 0;
}

cf 816E Karen and Supermarket的更多相关文章

  1. 816E. Karen and Supermarket 树形DP

    LINK 题意:给出n个商品,除第一个商品外,所有商品可以选择使用优惠券,但要求其前驱商品已被购买,问消费k以下能买几个不同的商品 思路:题意很明显就是树形DP.对于一个商品有三种选择,买且使用优惠券 ...

  2. CodeForces 816E Karen and Supermarket ——(树形DP)

    题意:有n件商品,每件商品都最多只能被买一次,且有一个原价和一个如果使用优惠券以后可以减少的价格,同时,除了第一件商品以外每件商品都有一个xi属性,表示买这个商品时如果要使用优惠券必须已经使用了xi的 ...

  3. Codeforces 815C Karen and Supermarket 树形dp

    Karen and Supermarket 感觉就是很普通的树形dp. dp[ i ][ 0 ][ u ]表示在 i 这棵子树中选择 u 个且 i 不用优惠券的最小花费. dp[ i ][ 1 ][ ...

  4. CF815C Karen and Supermarket

    题目链接 CF815C Karen and Supermarket 题解 只要在最大化数量的前提下,最小化花费就好了 这个数量枚举ok, dp[i][j][1/0]表示节点i的子树中买了j件商品 i ...

  5. CF815C Karen and Supermarket [树形DP]

    题目传送门 Karen and Supermarket On the way home, Karen decided to stop by the supermarket to buy some gr ...

  6. E. Karen and Supermarket

    E. Karen and Supermarket time limit per test 2 seconds memory limit per test 512 megabytes input sta ...

  7. 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 ...

  8. 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 ...

  9. 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 ...

随机推荐

  1. P4747 D’s problem(d)

    时间: 1000ms / 空间: 655360KiB / Java类名: Main 背景 冬令营入学测试题 描述 题目描述 小D是一名魔法师,它最喜欢干的事就是对批判记者了. 这次记者招待会上,记者对 ...

  2. Mysql主从数据同步cheksum问题

    做主从同步时出现问题,show slave status显示错误: Last_IO_Error: Got fatal error from master when reading data from ...

  3. pandas知识点(处理缺失数据)

    pandas使用浮点值NaN表示浮点和非浮点数组中的缺失数据: In [14]: string_data = Series(['aardvark','artichoke',np.nan,'avocad ...

  4. Building a Space Station POJ - 2031

    Building a Space Station POJ - 2031 You are a member of the space station engineering team, and are ...

  5. 用私有构造器或者枚举类型强化Singleton属性

    1.Singleton指仅仅被实例化一次的类.Singleton通常被用来代表那些本质上唯一的系统组件,如窗口管理器或者文件系统.使类称为Singleton会使它的客户端调试变的十分困难,因为无法给S ...

  6. 推荐Android几个优质的完整项目学习

    ==>来自于微信公众号==鸿洋.大家可以关注一波大神之作. 后台经常有人问我能不能推荐几个完整项目用于学习.借着周末的机会,给大家推荐几个,项目我基本都在本地运行过,并且会在文章末尾提供每个项目 ...

  7. MapReduce实现单词统计

     开发工具:IDEA mapreduce实现思路: Map阶段: a) 从HDFS的源数据文件中逐行读取数据 b) 将每一行数据切分出单词 c) 为每一个单词构造一个键值对(单词,1) d) 将键值对 ...

  8. cakephp中使用 find('count')方法

    对于find('count',array('group'=>'user_id')); Model.php中这样描述: /** * Handles the before/after filter ...

  9. WordCount by Java

    WordCount by Java 软测第二周作业 该项目github地址如下: https://github.com/YuQiao0303/WordCount 一.概述 项目WordCount的需求 ...

  10. python-生成器迭代器及递归调用

    生成器是一个可迭代的对象,它的执行会记住上一次返回时在函数体中的位置.对生成器第二次(或第 n 次)调用跳转至该函数上次执行位置继续往下执行,而上次调用的所有局部变量都保持不变. 生成器的特点:1.生 ...