Luogu 4377
题目分析:
-
仍然:设 s u m = ∑ t [ i ] , t o t = ∑ w [ i ] sum=\sum{t[i]},tot=\sum{w[i]} sum=∑t[i],tot=∑w[i]
-
转化为使 s u m t o t 最 大 , 并 且 t o t > = W \frac{sum}{tot}最大,并且tot>=W totsum最大,并且tot>=W
-
设最优值为 a n s ans ans,则有:
s u m t o t < = a n s \frac{sum}{tot}<=ans totsum<=ans
s u m − t o t ∗ a n s < = 0 sum-tot*ans<=0 sum−tot∗ans<=0
∑ ( t [ i ] − w [ i ] ∗ a n s ) < = 0 \sum{(t[i]-w[i]*ans)}<=0 ∑(t[i]−w[i]∗ans)<=0 -
二分 a n s ans ans,注意 r = 1 0 6 r=10^{6} r=106,用 01 01 01背包判定
Code:
#include <bits/stdc++.h>
using namespace std;
#define maxn 300
#define maxV 1010
#define re register
#define INF 2139062143
int n,V,w[maxn],t[maxn];
long long f[maxV];
inline void init_() {
freopen("a.txt","r",stdin);
}
inline int read_() {
int x=0,f=1;
char c=getchar();
while(c<'0'||c>'9') {
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9') {
x=(x<<1)+(x<<3)+c-'0';
c=getchar();
}
return x*f;
}
inline bool pd_(int x) {
memset(f,128,sizeof(f));
f[0]=0;
long long pdc=f[V];
for(re int i=1;i<=n;++i) {
for(re int j=V;j>=0;--j) {
if(f[j]==pdc) continue;
int jj=j+w[i];
if(jj>V) jj=V;
f[jj]=max(f[jj],f[j]+t[i]-(long long)w[i]*x);
}
}
if(f[V]>=0) return true;
else return false;
}
void readda_() {
n=read_();V=read_();
for(re int i=1;i<=n;++i) {
w[i]=read_();
t[i]=read_();
//r=max(r,(t[i]/w[i])*1000);
t[i]*=1000;
}
int l=0,r=1e6,ans,mid;
while(l<=r) {
mid=(l+r)>>1;
if(pd_(mid)) {
l=mid+1;
ans=mid;
}
else r=mid-1;
}
printf("%d",ans);
}
int main() {
init_();
readda_();
return 0;
}