• AT4120 [ARC096D] Sweet Alchemy


    题目传送门

    分析:
    看到这个限制条件构成了一个树形结构,相当于儿子节点的生产数一定不小于父亲节点,且不比父亲节点多超过(D)
    差分一下,如果一个节点要制造物品,那么其子树内的节点全部都制造一个物品,非根节点最多造(D)个物品
    效果相同,并且将每个节点的代价和收益变为子树和,我们就可以脱离树形结构直接多重背包了
    但是(Dleq 10^9)不能够枚举
    我们回到最开始学动规背包时,相想必大家在解决背包问题时一定想过一个贪心:
    一个物品重量为(w),价值为(v),我们把物品按(frac{v}{w})从大到小排序,贪心加入
    这样做会在当背包剩余空间不够大的时候出现问题,相信大家也把自己驳倒过
    但是在背包空间足够大时,这样的做法就没有问题
    我们可以在背包空间不够大的时候做多重背包,剩余的体积用于贪心加入物品
    假设有两个物品(i,j)满足(frac{v_i}{w_i}>frac{v_j}{w_j}),那么在收益相等(选了(v_j)(i),选了(v_i)(j))的情况下,选(v_j)(i)显然会更优
    从而在比(frac{v_i}{w_i})大的物品还能加的时候,比(frac{v_i}{w_i})小的至多会选(v_i-1)
    我们这道题一个点的(v)为子树和,最大为(n)
    相当于做背包的每种物品最多有(min(n,D))个,背包体积最大为(n^3)
    使用二进制分组优化一下,复杂度可以接受
    剩下的暴力加入就好了
    总复杂度(O(n^4logX))

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<algorithm>
    #include<queue>
    #include<bitset>
    #include<map>
    #include<set>
    
    #define maxn 55
    #define maxm 125005
    #define INF 0x3f3f3f3f
    #define MOD 1000000007
    
    using namespace std;
    
    inline int getint()
    {
    	int num=0,flag=1;char c;
    	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
    	while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
    	return num*flag;
    }
    
    int n,X,d;
    int fa[maxn];
    struct node{
    	long long v;
    	int w,id;
    }a[maxn];
    inline bool cmp(node a,node b){return a.w*b.v>b.w*a.v;}
    long long dp[maxm];
    
    int main()
    {
    	n=getint(),X=getint(),d=getint();
    	a[1].v=getint();
    	for(int i=2;i<=n;i++)a[i].v=getint(),fa[i]=getint();
    	for(int i=1;i<=n;i++)a[i].id=i,a[i].w=1;
    	for(int i=n;i>1;i--)a[fa[i]].v+=a[i].v,a[fa[i]].w+=a[i].w;
    	int L=min(n,d);
    	memset(dp,INF,sizeof dp),dp[0]=0;
    	for(int i=1;i<=n;i++)
    	{
    		int x=L;
    		for(int j=0;(1<<j)<=x;j++)
    		{
    			int w=a[i].w<<j;
    			long long v=a[i].v<<j;
    			for(int k=maxm-1;k>=w;k--)dp[k]=min(dp[k],dp[k-w]+v);
    			x-=1<<j;
    		}
    		if(x)
    		{
    			int w=a[i].w*x;
    			long long v=a[i].v*x;
    			for(int j=maxm-1;j>=w;j--)dp[j]=min(dp[j],dp[j-w]+v);
    		}
    	}
    	sort(a+1,a+n+1,cmp);
    	while(a[n].id!=1)n--;
    	long long ans=0;
    	for(int i=0;i<maxm;i++)
    	{
    		if(dp[i]>X)continue;
    		long long w=i,v=dp[i];
    		for(int j=1;j<n;j++)
    		{
    			long long c=min(1ll*d-L,(X-v)/a[j].v);
    			w+=c*a[j].w,v+=c*a[j].v;
    		}
    		long long c=(X-v)/a[n].v;
    		w+=c*a[n].w,v+=c*a[n].v;
    		ans=max(ans,w);
    	}
    	printf("%lld
    ",ans);
    }
    

  • 相关阅读:
    5285: [Hnoi2018]寻宝游戏
    CF 1117 E. Decypher the String
    4515: [Sdoi2016]游戏
    CF 1051 G. Distinctification
    4820: [Sdoi2017]硬币游戏
    HNOI2019游记
    最近公共祖先(LCT)
    [WC2006]水管局长(LCT)
    P4178 Tree(点分治)
    二维凸包
  • 原文地址:https://www.cnblogs.com/Darknesses/p/13267355.html
Copyright © 2020-2023  润新知