【01分数规划+01背包】Talent Show

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/monochrome00/article/details/88534564

题目链接<http://10.7.88.2/CLanguage/showproblem?problem_id=2268>


题意:

给出n头奶牛的重量w和才艺值t,要求挑出若干只牛,使得\sum{w}大于等于w,且\tfrac{\sum{t}}{\sum{w}}最大。


题解:

01分数规划:设\tfrac{\sum{t}}{\sum{w}}=v,则\sum{t}-\sum{w}*v=0,如果\sum{t}-\sum{w}*v>0,证明v偏小,否则v偏大。这样就可以二分答案了。

判断的时候用01背包来判断能否挑出一些体重之和大于等于w的奶牛,且\sum{t}-\sum{w}*v>0

这时候的背包就只要枚举到w即可,dp[w]表示的是所有大于等于w中最大的状态。


#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#define ll long long
using namespace std;
const ll N=1e3+7;
ll md;
ll a[N],b[N];
ll w,n;
ll dp[N];
bool jg(ll md){
    memset(dp,-125,sizeof(dp));
    dp[0]=0;
    for(ll i=1;i<=n;i++){
        for(ll j=w;j>=0;j--){
            if(dp[j]<=dp[w+1]) continue;
            ll k=min(w,a[i]+j);
            dp[k]=max(dp[k],dp[j]+b[i]-md*a[i]);
        }
    }
    return dp[w]>=0;
}
int main()
{
    scanf("%lld%lld",&n,&w);
    for(ll i=1;i<=n;i++){
        scanf("%lld%lld",&a[i],&b[i]);
        b[i]*=1000;
    }
    ll lo=0,hi=1e6,ans;
    while(lo<=hi){
        md=lo+hi>>1;
        if(jg(md)) ans=md,lo=md+1;
        else hi=md-1;
    }
    printf("%lld\n",ans);
}

猜你喜欢

转载自blog.csdn.net/monochrome00/article/details/88534564