• 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;
    }
    
    
  • 相关阅读:
    tomcat websocket 实现网页在线即时聊天
    可编辑DIV 光标位置 处理
    Java匿名内部类使用与示例
    JS判断值是否是数字
    BAT等大型互联网公司的网站架构演化历程
    GIT总结
    5.1_二叉树
    4.4_8种常用排序算法5(基数排序)
    4.3_8种常用排序算法4(归并排序)
    4.3_8种常用排序算法3(选择排序:简单选择排序+堆排序)
  • 原文地址:https://www.cnblogs.com/cjl-world/p/14054129.html
Copyright © 2020-2023  润新知