zoukankan      html  css  js  c++  java
  • AcWing 171. 送礼物

    STL,vector,unique,sort,upper_bound也过了。
    此题部分代码被卡的原因是

    没有排序,导致两部分 sum>m 的剪枝效果不一,要是前半部分的重量较小,枚举 (2^{23}) 自然就挂了。
    处理方法有两种

    • random_shuffle() ,打乱顺序,使剪枝均匀分布。
    • sort() , 我的建议是升序,然后令 dfs1() 的深度最大为 20.这样前半部分最多 (2^{20}) 个数,后半部分因为数都较大,大部分被剪掉了,剩的不多,复杂度也可以接受。
    #include<set>
    #include<map>
    #include<queue>
    #include<stack>
    #include<ctime>
    #include<cmath>
    #include<bitset>
    #include<vector>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    typedef long long LL;
    typedef unsigned long long ULL;
    //折半搜索
    const int N=56;
    const LL INF=1e16;
    
    LL n,m,w[N],ans; 
    vector<LL> v;
    
    void dfs1(int step,int limit,LL sum)
    {
    	if(sum>m) return;
    	if(step==limit+1) {
    		ans=max(ans,sum);
    		v.push_back(sum);
    		return;
    	}
    	dfs1(step+1,limit,sum+w[step]);
    	dfs1(step+1,limit,sum);
    }
    
    void dfs2(int step,int limit,LL sum)
    {
    	if(sum>m) return;
    	if(step==limit+1) {
    		// sum+v[u] <= m ---> v[u]<=m-sum
    		ans=max(ans,sum);
    		int id=(int)(upper_bound(v.begin(),v.end(),m-sum)-v.begin())-1;
    		if(id>=0&&v[id]+sum<=m) ans=max(ans,v[id]+sum);
    		return; 
    	}
    	dfs2(step+1,limit,sum+w[step]);
    	dfs2(step+1,limit,sum);
    }
    
    int main()
    {
    	cin>>m>>n;
    	for(int i=1;i<=n;i++)
    		scanf("%lld",&w[i]);
    	sort(w+1,w+n+1);
    	int tmp=min(n,20ll);
    	dfs1(1,tmp,0);
    	sort(v.begin(),v.end());
    	v.erase(unique(v.begin(),v.end()),v.end());
    	dfs2(tmp+1,n,0);
    	cout<<ans;
    	return 0;
    }
    
    
  • 相关阅读:
    麦肯锡矩阵导航图
    以业务为核心的云原生体系建设
    万字长文拿下HTTP
    人人都该懂的埋点知识
    淘宝的技术架构
    五步,快速理解一个行业
    一文读懂用户分层
    python13day
    python12day
    python11day
  • 原文地址:https://www.cnblogs.com/cjl-world/p/14054129.html
Copyright © 2011-2022 走看看