cf 816E Karen and Supermarket
题目大意
给定\(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的更多相关文章
- 816E. Karen and Supermarket 树形DP
		
LINK 题意:给出n个商品,除第一个商品外,所有商品可以选择使用优惠券,但要求其前驱商品已被购买,问消费k以下能买几个不同的商品 思路:题意很明显就是树形DP.对于一个商品有三种选择,买且使用优惠券 ...
 - CodeForces 816E Karen and Supermarket  ——(树形DP)
		
题意:有n件商品,每件商品都最多只能被买一次,且有一个原价和一个如果使用优惠券以后可以减少的价格,同时,除了第一件商品以外每件商品都有一个xi属性,表示买这个商品时如果要使用优惠券必须已经使用了xi的 ...
 - 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 ...
 
随机推荐
- 多种语言书写 “ HelloWorld ”
			
最基本的C: #include<stdio.h> int main(int argc, char const *argv[]) { printf("HelloWorld\n&qu ...
 - 模态框获取内容jQuery
			
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
 - 用dom1来实现,根据光标移动自动给表单加上背景色,光标移开自动去除背景色
			
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
 - ajaxfileuplod 上传文件 essyui  laoding 效果,防止重复上传文件
			
//放于上传前 function ajaxLoading(){ $("<div class=\"datagrid-mask\"></div>&qu ...
 - SpringSecurity项目报错
			
启动时,提示: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory be ...
 - JZOJ 5773. 【NOIP2008模拟】简单数学题
			
5773. [NOIP2008模拟]简单数学题 (File IO): input:math.in output:math.out Time Limits: 1000 ms Memory Limits ...
 - django开发基础
			
一.配置静态文件 https://www.cnblogs.com/lshedward/p/10351051.html 二.路由分发 https://www.cnblogs.com/lshedward/ ...
 - ubuntu版本查看
			
cat /proc/version uname -a lsb_release -a
 - HDU4616 树形DP+三次深搜
			
这题和之前那个HDU2616有着奇妙的异曲同工之处..都是要求某个点能够到达的最大权重的地方... 但是,这题加了个限制,要求最多只能够踩到C个陷阱,一单无路可走或者命用光了,就地开始清算总共得分之和 ...
 - Git-起步
			
Git命令行 只要输入git,Git就会不带任何参数地列出它的选项和最常用的子命令. 要得到一个完整的git子命令列表,可以输入git help --all 显示版本号 git --version 每 ...