Codeforces - Karen and Supermarket

题目链接:Codeforces - Karen and Supermarket


每一个优惠券之间构成了一颗树,要子节点能优惠,就必须选父亲节点优惠。

很明显是一个树上背包。直接做即可。

dp[i][j][0/1]代表i节点选j个,是否用优惠券。


AC代码:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e3+10;
int n,b,c[N],d[N],dp[N][N][2],sz[N];
vector<int> g[N];
void dfs(int x){
	sz[x]=1;
	dp[x][0][0]=0,dp[x][1][0]=c[x],dp[x][1][1]=c[x]-d[x];
	for(auto to:g[x]){
		dfs(to);
		for(int i=sz[x];i>=0;i--){
			for(int j=0;j<=sz[to];j++)	if(i+j<=n){
				dp[x][i+j][1]=min(dp[x][i+j][1],dp[x][i][1]+dp[to][j][1]);
				dp[x][i+j][1]=min(dp[x][i+j][1],dp[x][i][1]+dp[to][j][0]);
				dp[x][i+j][0]=min(dp[x][i+j][0],dp[x][i][0]+dp[to][j][0]);
			}
		}
		sz[x]+=sz[to];	
	}
}
signed main(){
	cin>>n>>b>>c[1]>>d[1];	memset(dp,0x3f,sizeof dp);
	for(int i=2,x;i<=n;i++){
		cin>>c[i]>>d[i]>>x;	g[x].push_back(i);
	}
	dfs(1);
	for(int i=n;i>=1;i--)	if(dp[1][i][1]<=b||dp[1][i][0]<=b){
		return cout<<i,0;
	}
	cout<<0;
	return 0;
}
发布了553 篇原创文章 · 获赞 242 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/weixin_43826249/article/details/104181330