zoukankan      html  css  js  c++  java
  • 「HDU 5887」Herbs Gathering (背包)

    题意:原题在这

    给定背包容量和n个物品每个的价值和重量,求能装的物品的最大价值。(采药)

    附一组自己出的数据,虽然不够刁钻但是查错够用:

    5 100
    101 200
    99 1
    1 2
    98 20
    2 50

    做法:(详见行内注释)


    做法1:

    1. 因为dp解法的复杂度为O(V*N),w[i]和v[i]都在10e9,所以不能dp只能dfs

    2. 一种按体积排序的做法:

        按照体积由大到小排序,如果后面能取完的就直接取完;

        如果后面一直选择最优策略(能获得的最大价值加上已有的)都不好于现在的答案则break;

        (参考:https://blog.csdn.net/qq_21057881/article/details/52577874)

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define maxn 105
    typedef long long ll;
    
    int n,k;
    long long sw[maxn],sv[maxn];
    struct node  
    {
        int w,v;
        double rate;//物品的性价比
    }pack[maxn];
    
    bool cmp(node x,node y) {return x.w>y.w;}
    
    long long ans=0;
    void dfs(int pos,int maxx,ll target)
    {
        if(pos==n)//尽量取完
        {
            if(maxx>=pack[pos].w)//如果能装下
                ans=max(ans,target+pack[pos].v);
            else//装不下
                ans=max(ans,target);
            return;
        }
        if(sw[pos]<=maxx)//还能装
        {
            ans=max(ans,target+sv[pos]);
            return;
        }
        if(target+sv[pos]<=ans) return;//要搜的+搜到的 都不好于现在,不搜
        dfs(pos+1,maxx,target);
        if(maxx>=pack[pos].w)
            dfs(pos+1,maxx-pack[pos].w,target+pack[pos].v);
    }
    
    int main()
    {
        while(scanf("%d%d",&n,&k)!=EOF)
        {
            ans=0; sw[n+1]=0; sv[n+1]=0;
            for(int i=1;i<=n;i++)
            {
                cin>>pack[i].w>>pack[i].v;
                pack[i].rate = 1.0*pack[i].v/pack[i].w;//计算性价比
            }
            sort(pack+1,pack+n+1,cmp);
            for(int i=n;i>=1;i--)
            {
                sv[i]=sv[i+1]+pack[i].v;
                sw[i]=sw[i+1]+pack[i].w;
            }
            dfs(1,k,0);
            cout<<ans<<endl;
        }
    }

    做法2:

    1. 先按性价比排序,直接把不能选的去掉,之后搜索的时候若剩下的背包空间都以最高性价比选时不会比已找到的最优解更好时则剪枝

    (参考:https://blog.csdn.net/consciousman/article/details/52572702)

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define maxn 105
    #define INF 0x3f3f3f3f
    typedef long long LL;
    
    int n,k;
    long long cnt,ans;
    struct node  
    {
        long long w,v;
        double r;//物品的性价比
    }pack[maxn];
    
    bool cmp(node x,node y) {return x.r>y.r;}
    
    int check(int i,long long sw,long long sv)
    {
        for(int j=i; j<cnt && sw<k;j++)
        {
            if(pack[j].w+sw<=k)
            {
                sw+=pack[j].w;
                sv+=pack[j].v;
            }
            else
            {
                sv+=pack[j].r*(k-sw);
                sw=k;
            }
        }
        return sv>ans;
    }
    
    void dfs(int i,long long sw,long long sv)
    {
        ans=max(ans,sv);
        if(i<cnt && check(i,sw,sv))
        {
            if(sw+pack[i].w<=k)
                dfs(i+1,sw+pack[i].w,sv+pack[i].v);
            dfs(i+1,sw,sv);
        }
    }
    
    int main()
    {
        while(scanf("%d %d",&n,&k)!=EOF)
        {
            cnt=ans=0;
            for(int i=1;i<=n;i++)
            {
                long long w,v;
                cin>>w>>v;
                if(w<=k)
                {
                    pack[++cnt].w=w;
                    pack[cnt].v=v;
                    pack[cnt].r=(v+0.0)/w;
                    // pack[cnt++]=(node){w, v, (v+0.0)/w};
                }
            }
            sort(pack+1,pack+1+cnt,cmp);
            dfs(0,0,0);
            cout<<ans<<endl;
        }
        return 0;
    }
  • 相关阅读:
    《程序员修炼之道》——第二章 注重实效的途径(三)
    《程序员修炼之道》——第二章 注重实效的途径(二)
    《程序员修炼之道》——第二章 注重实效的途径(一)
    win10 磁盘占用高--- 禁用用户改善反馈 CompatTelRunner.exe
    ffmpeg拼接多个音频
    词云-wordcloud
    大数据指数日常应用
    搜索过滤Tip : title,site(搜标题和搜网站)
    eclipse下查看java源码设置
    sqlplus sys as sysdba
  • 原文地址:https://www.cnblogs.com/LocaEtric/p/9275655.html
Copyright © 2011-2022 走看看