zoukankan      html  css  js  c++  java
  • P4799 [CEOI2015 Day2]世界冰球锦标赛

    \(0-1\)背包解法

    适用数据范围:\(N≤40,M≤10^6\)
    状态表示:\(f(i,j)\):从前\(i\)个物品中选,花费不超过(小于等于)\(j\)的方案数。
    最后累加\(f(n,0~m)\)即可。

    const int N=45,M=1e6+10;
    LL price[N];
    LL f[M];
    LL n,m;
    LL ans;
    
    int main()
    {
        cin>>n>>m;
    
        for(int i=1;i<=n;i++) cin>>price[i];
    
        f[0]=1;
        for(int i=1;i<=n;i++)
        {
            for(int j=m;j>=price[i];j--)
            {
                f[j]+=f[j-price[i]];
            }
        }
    
        for(int i=0;i<=m;i++) ans+=f[i];
        cout<<ans<<endl;
    
        //system("pause");
    }
    

    折半搜索——正解

    我们可以将所有比赛分成两部分,对这两部分分别进行指数型枚举,然后使用vector来储存搜索过程中产生的可能的花费。

    最后再将两部分进行合并,得出最终的答案。

    时间复杂度:\(O(2^{\frac{n}{2}}log2^{\frac{n}{2}})\)

    const int N=45;
    LL price[N];
    vector<LL> suml;
    vector<LL> sumr;
    LL n,m;
    LL ans;
    
    void dfs(int l,int r,LL sum,vector<LL> &v)
    {
        if(l>r)
        {
            v.pb(sum);
            return;
        }
        if(sum + price[l] <= m) dfs(l+1,r,sum+price[l],v);
        dfs(l+1,r,sum,v);
    }
    
    int main()
    {
        cin>>n>>m;
    
        for(int i=0;i<n;i++) cin>>price[i];
    
        dfs(0,n/2-1,0,suml);
        dfs(n/2,n-1,0,sumr);
    
        sort(suml.begin(),suml.end());
    
        for(int i=0;i<sumr.size();i++)
        {
            ans+=upper_bound(suml.begin(),suml.end(),m-sumr[i])-suml.begin();
        }
    
        cout<<ans<<endl;
        //system("pause");
    }
    
  • 相关阅读:
    Android入门第六篇之ListView (一)
    mysql触发器的作用及语法
    查询记录时rs.previous()的使用
    Microsoft Visual C++ Runtime Library Runtime Error的解决的方法
    Ubuntu中编译链接Opencv应用的简便方式
    24点经典算法
    CMS系统简介(从简介到使用)
    编程学习资源
    Django是什么
    Thinkphp中的自动验证
  • 原文地址:https://www.cnblogs.com/fxh0707/p/14128743.html
Copyright © 2011-2022 走看看