zoukankan      html  css  js  c++  java
  • 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);
    }
    

  • 相关阅读:
    【leetcode】106. Construct Binary Tree from Inorder and Postorder Traversal
    【leetcode】105. Construct Binary Tree from Preorder and Inorder Traversal
    【leetcode】236. Lowest Common Ancestor of a Binary Tree
    【leetcode】235. Lowest Common Ancestor of a Binary Search Tree
    【leetcode】352. Data Stream as Disjoint Intervals
    【leetcode】897. Increasing Order Search Tree
    【leetcode】900. RLE Iterator
    BEC listen and translation exercise 26
    BEC listen and translation exercise 25
    BEC listen and translation exercise 24
  • 原文地址:https://www.cnblogs.com/Darknesses/p/13267355.html
Copyright © 2011-2022 走看看