原题: http://acm.zjnu.edu.cn/CLanguage/showproblem?problem_id=2268
n个物品,w值与v值,要求 的前提下 最大
比赛的时候感觉没没没问题啊。。。01分数规划白学了。
解析:
先01分数规划,再dp即可
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(register int i=a;i<=b;i++)
int n,W;
int w[260],v[260];
struct node{
double val,w;
bool operator<(const node &rhs)const{
return val>rhs.val;
}
}e[260];
const double eps=1e-7;
double dp[1009];
bool check(double x){
rep(i,1,n){
e[i].w=1.0*w[i];
e[i].val=1.0*v[i]-x*w[i];
}
sort(e+1,e+1+n);
int i=1;
double sumv=0;
double sumw=0;
for(;i<=n;i++){//大于0的一定要选
if(e[i].val>=0)sumv+=e[i].val,sumw+=e[i].w;
else break;
}
if(sumw>=W)return 1;
int en=(int)round(1.0*W-sumw);
rep(i,1,en)dp[i]=-1e18;
dp[0]=0;
for(;i<=n;i++){
for(int j=en;j>=0;j--){
int to=j+e[i].w;
if(to>en)to=en;
dp[to]=max(dp[to],dp[j]+e[i].val);
}
}
if(dp[en]+sumv>0)return 1;
return 0;
}
int main(){
cin>>n>>W;
double l=1e18,r=-1e18;
rep(i,1,n){
scanf("%d%d",w+i,v+i);
l=min(l,1.0*v[i]/w[i]);
r=max(r,1.0*v[i]/w[i]);
}
while(r-l>eps){
double mid=(l+r)/2;
if(check(mid))l=mid;
else r=mid;
}
printf("%.0f\n",floor(r*1000.0));
}