• 《算法竞赛进阶指南》0x24迭代加深 子集和问题


    题目链接:https://www.acwing.com/problem/content/173/

    要求从n件物品中选出若干件,重量之和不超过w并且最接近w,由于有45件最多,所以O(2^n)时间复杂度过高,可以考虑减半先搜索出结果,用另一半在前一半中二分寻找,

    最终拼成结果,时间复杂度约为O(2^n/2*n)。中间有一个优化是将所有物品的重量进行降序排序,这样做可以使得子集和更快的趋近w和,决策的数量将会变少。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<vector>
    #include<algorithm>
    using namespace std;
    #define maxn 100
    typedef long long ll;
    unsigned int  n,w,g[maxn];
    vector<unsigned int > v; 
    unsigned int ans;
    int m ;
    void dfs1(int now,unsigned int tot){//搜索前一半 
        if(!now){
            v.push_back(tot);
            return ;
        }
        dfs1(now-1,tot);//不选第i件,
        if(g[now]+tot <= w)dfs1(now-1,g[now]+tot); 
    }
    void dfs2(int now,unsigned int  tot){
        if(now==n+1){
            unsigned int y=*--upper_bound(v.begin(),v.begin()+m,w-tot);//查找最后一个小于等于w-tot的值 
            ans=max(ans,tot+y);
            return; 
        }
        dfs2(now+1,tot);
        if(g[now]+tot <= w)dfs2(now+1,g[now]+tot);
    }
    bool cmp(unsigned int &a,unsigned int &b){return a>b;}
    int main(){
        cin>>w>>n;
        for(int i=1;i<=n;i++)cin>>g[i];
        sort(g+1,g+n+1,cmp);//优化搜索顺序 
        int k=n/2+2;
        dfs1(k,0);//先处理出前一半 
        sort(v.begin(),v.end());
        m=unique(v.begin(),v.end())-v.begin();
        dfs2(k+1,0);
        cout<<ans<<endl;
    }
  • 相关阅读:
    第三次上机作业
    第二次实训作业
    java第二次作业
    java程序设计第一次作业
    实训作业1
    java2
    我的第一次java作业
    第六次实训作业异常处理
    事件处理程序
    实训作业4
  • 原文地址:https://www.cnblogs.com/randy-lo/p/13164627.html
Copyright © 2020-2023  润新知