题目大意

给定\(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. 多种语言书写 “ HelloWorld ”

    最基本的C: #include<stdio.h> int main(int argc, char const *argv[]) { printf("HelloWorld\n&qu ...

  2. 模态框获取内容jQuery

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. 用dom1来实现,根据光标移动自动给表单加上背景色,光标移开自动去除背景色

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. ajaxfileuplod 上传文件 essyui laoding 效果,防止重复上传文件

    //放于上传前 function ajaxLoading(){ $("<div class=\"datagrid-mask\"></div>&qu ...

  5. SpringSecurity项目报错

    启动时,提示: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory be ...

  6. JZOJ 5773. 【NOIP2008模拟】简单数学题

    5773. [NOIP2008模拟]简单数学题 (File IO): input:math.in output:math.out Time Limits: 1000 ms  Memory Limits ...

  7. django开发基础

    一.配置静态文件 https://www.cnblogs.com/lshedward/p/10351051.html 二.路由分发 https://www.cnblogs.com/lshedward/ ...

  8. ubuntu版本查看

    cat /proc/version uname -a lsb_release -a

  9. HDU4616 树形DP+三次深搜

    这题和之前那个HDU2616有着奇妙的异曲同工之处..都是要求某个点能够到达的最大权重的地方... 但是,这题加了个限制,要求最多只能够踩到C个陷阱,一单无路可走或者命用光了,就地开始清算总共得分之和 ...

  10. Git-起步

    Git命令行 只要输入git,Git就会不带任何参数地列出它的选项和最常用的子命令. 要得到一个完整的git子命令列表,可以输入git help --all 显示版本号 git --version 每 ...