题目描述

Farmer John要带着他的头奶牛,方便起见编号为,到农业展览会上去,参加每年的达牛秀!他的第ii头奶牛重量为,才艺水平为,两者都是整数。

在到达时,Farmer John就被今年达牛秀的新规则吓到了:

(一)参加比赛的一组奶牛必须总重量至少为(这是为了确保是强大的队伍在比赛,而不仅是强大的某头奶牛),并且

(二)总才艺值与总重量的比值最大的一组获得胜利。

FJ注意到他的所有奶牛的总重量不小于,所以他能够派出符合规则(一)的队伍。帮助他确定这样的队伍中能够达到的最佳的才艺与重量的比值。

输入描述:

输入的第一行包含。下面行,每行用两个整数描述了一头奶牛。

输出描述:

请求出Farmer用一组总重量最少为W的奶牛最大可能达到的总才艺值与总重量的比值。如果你的答案是AA,输出1000A向下取整的值,以使得输出是整数(当问题中的数不是一个整数的时候,向下取整操作在向下舍入到整数的时候去除所有小数部分)。

示例1

输入
3 15
20 21
10 11
30 31
输出
1066
说明
在这个例子中,总体来看最佳的才艺与重量的比值应该是仅用一头才艺值为11、重量为10的奶牛,但是由于我们需要至少15单位的重量,最优解最终为使用这头奶牛加上才艺值为21、重量为20的奶牛。这样的话才艺与重量的比值为,乘以1000向下取整之后得到1066。

解答

解法:这题改编自最大化平均值,但却是贪心->01背包问题

我们需要找到当前重量的最大看其是否

递推关系:

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N=253;
const double INF = 0x3f3f3f3f;
int w[N], v[N];
double p[N], dp[1003];
int n,W;
const double eps=1e-8;
bool C(double  x)
{
    for(int i=0; i<n; i++)
    {
        p[i]=(double)(v[i]-x*w[i]);
    }
    for(int i=0; i<=W; i++) dp[i]=-INF;
    dp[0]=0;                               //重量为0时的∑p[i]=0
    for(int i=0; i<n; i++)
    {
        for(int j=W; j>=0; j--)
        {
            if(W<=w[i]+j)   dp[W]=max(dp[W],dp[j]+p[i]);
            else if(W>=w[i]+j) dp[w[i]+j]=max(dp[w[i]+j],dp[j]+p[i]);
        }
    }
    return dp[W]>=0;
}
int main()
{
    double ans;
     cin>>n>>W;
    for(int i=0; i<n; i++) cin>>w[i]>>v[i];
    double l=0, r=3000;
     while(r-l>eps)
    {
        double mid=(l+r)/2;
        if(C(mid))  l=mid, ans=mid;
        else r=mid;
    }
    cout<<(int)(ans*1000.0)<<endl;
    return 0;
}

来源:Hcacai