1. 程式人生 > >「HDU 5887」Herbs Gathering

「HDU 5887」Herbs Gathering

排序 ans con 計算 www sci php show cio

題意:原題在這

給定背包容量和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;
}

「HDU 5887」Herbs Gathering