原题
挂个链接BZOJ
Solution
分析:
显然我们可以直接(01)分数+(dp)然后就AC了...
注意一下(dp)的更新方式.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<queue>
#include<algorithm>
#define ll long long
#define re register
using namespace std;
inline int gi(){
int sum=0,f=1;char ch=getchar();
while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
return f*sum;
}
inline ll gl(){
ll sum=0,f=1;char ch=getchar();
while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
return f*sum;
}
const double eps=1e-6;
int n,W,w[310],t[310];
double s[310],dp[310][1020];
bool check(double mid){
dp[0][0]=0;
for(re int i=1;i<=n;i++)s[i]=t[i]-mid*w[i];
for(re int i=1;i<=n;i++)
for(re int j=0;j<=W;j++){
dp[i][j]=max(dp[i][j],dp[i-1][j]);
dp[i][min(W,j+w[i])]=max(dp[i][min(W,j+w[i])],dp[i-1][j]+s[i]);
}
return dp[n][W]>=0;
}
int main(){
n=gi();W=gi();
for(re int i=1;i<=n;i++)
w[i]=gi(),t[i]=gi();
double l=0,r=1e6;
while(r-l>eps){
double mid=(l+r)/2;
for(re int i=0;i<=n;i++)
for(re int j=0;j<=W;j++)
dp[i][j]=-1e18;
if(check(mid))l=mid;
else r=mid;
}
printf("%d
",(int)(l*1000));
return 0;
}