5281: [Usaco2018 Open]Talent Show
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 140 Solved: 103
Description
FarmerJohn要带着他的N头奶牛,方便起见编号为1…N,到农业展览会上去,参加每年的达牛秀!他的第i头奶牛重
量为wi,才艺水平为ti,两者都是整数。在到达时,FarmerJohn就被今年达牛秀的新规则吓到了:
(一)参加比赛的一组奶牛必须总重量至少为W
(这是为了确保是强大的队伍在比赛,而不仅是强大的某头奶牛),并且
(二)总才艺值与总重量的比值最大的一组获得胜利。
FJ注意到他的所有奶牛的总重量不小于W,所以他能够派出符合规则(一)的队伍。帮助他确定这样的队伍中能够
达到的最佳的才艺与重量的比值。
Input
输入的第一行包含N和W。下面N行,每行用两个整数wi和ti描述了一头奶牛。
1≤N≤250
1≤W≤1000
1≤wi≤10^6
1≤ti≤10^3
Output
请求出Farmer用一组总重量最少为W的奶牛最大可能达到的总才艺值与总重量的比值。
如果你的答案是A,输出1000A向下取整的值,以使得输出是整数
(当问题中的数不是一个整数的时候,向下取整操作在向下舍入到整数的时候去除所有小数部分)。
Sample Input
3 15
20 21
10 11
30 31
Sample Output
1066
在这个例子中,总体来看最佳的才艺与重量的比值应该是仅用一头才艺值为11、重量为10的奶牛,但是由于我们需
要至少15单位的重量,最优解最终为使用这头奶牛加上才艺值为21、重量为20的奶牛。这样的话才艺与重量的比值
为(11+21)/(10+20)=32/30=1.0666666...,乘以1000向下取整之后得到1066。
解析:
0/1分数规划+背包DP
代码:
#include <bits/stdc++.h>
using namespace std;
const double inf=1e9;
const int Max=255;
int n,m;
double l,r,mid,f[10010];
struct shu{double w,t;};
shu a[Max];
inline int get_int()
{
int x=0,f=1;
char c;
for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
if(c=='-') f=-1,c=getchar();
for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
return x*f;
}
inline bool check(double mid)
{
for(int i=1;i<=m;i++) f[i]=-inf;
for(int i=1;i<=n;i++)
for(int j=m;j>=0;j--)
{
// if(f[j]==-inf) continue;
int x=j+a[i].w;
if(x>m) x=m;
f[x]=max(f[x],f[j]+a[i].t-mid*a[i].w);
}
return f[m]>0;
}
inline void solve()
{
l=0.0,r=1e4;
while(r-l>=1e-5)
{
mid=(l+r)/2;
if(check(mid)) l=mid;
else r=mid;
}
}
int main()
{
n=get_int(),m=get_int();
for(int i=1;i<=n;i++) a[i].w=get_int(),a[i].t=get_int();
solve();
cout<<(int)(l*1000);
return 0;
}