題解 [USACO18OPEN] Talent Show
題目描述
題目描述網上有。
具體做法
01分數規劃入門題!
考慮我們爲每個數設一個,只有兩種取值。
那麼題目要求的式子爲:
相當於我們要求解每個的取值,同時滿足。
考慮二分答案。
式子變成:
移項後變成
把看成,那麼就可以做一個簡單揹包來判斷了。
/*******************************
Author:galaxy yr
LANG:C++
Created Time:2019年10月27日 星期日 21時56分52秒
*******************************/
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
struct IO{
template<typename T>
IO & operator>>(T&res)
{
T q=1;char ch;
while((ch=getchar())<'0' or ch>'9')if(ch=='-')q=-q;
res=(ch^48);
while((ch=getchar())>='0' and ch<='9') res=(res<<1)+(res<<3)+(ch^48);
res*=q;
return *this;
}
}cin;
const int maxn=255;
const double eps=1e-4;
int n,W,w[maxn],t[maxn];
double val[maxn],f[10000];
double ans;
bool check(double mid)
{
for(int i=1;i<=n;i++)
val[i]=t[i]-w[i]*mid;
for(int i=1;i<=2*W;i++) f[i]=-1e9;
f[0]=0;
for(int i=1;i<=n;i++)
{
for(int j=W*2;j>=w[i];j--)
{
f[j]=max(f[j],f[j-w[i]]+val[i]);
if(f[j]>=0 && j>=W)
return 1;
}
}
return 0;
}
int main()
{
//freopen("p4377.in","r",stdin);
//freopen("p4377.out","w",stdout);
cin>>n>>W;
for(int i=1;i<=n;i++)
cin>>w[i]>>t[i];
double l=0,r=1e9,mid;
while((r-l)>eps)
{
mid=(l+r)/2;
if(check(mid))
l=mid,ans=mid;
else
r=mid;
}
int res=(int)(ans*1000);
printf("%d\n",res);
return 0;
}