Descripción del Título:
Ideas de resolución de problemas:
Supongamos que Xiaomi solo quiere comprar 3 artículos y finalmente compra los artículos i, j, ki, j, ki ,j ,k tal que el valor máximo buscado seamax maxm a x . Luego está la relaciónv [i] + v [j] + v [k] c [i] + c [j] + c [k] = max \ frac {v [i] + v [j] + v [ k]} {c [i] + c [j] + c [k]} = máx.c [ i ] + c [ j ] + c [ k ]v [ i ] + v [ j ] + v [ la k ]=m a x成立, 也 即v [i] + v [j] + v [k] - máx ∗ c [i] - máx ∗ c [j] - máx ∗ c [k] = 0 v [i] + v [j] + v [k] -max * c [i] -max * c [j] -max * c [k] = 0v [ i ]+v [ j ]+v [ k ]-m a x∗c [ i ]-m a x∗c [ j ]-m a x∗c [ k ]=Se establece 0 . Si solo adivinamos un númeroxxx去 替代 "v [i] + v [j] + v [k] - máx ∗ c [i] - máx ∗ c [j] - máx ∗ c [k] v [i] + v [j] + v [k] -max * c [i] -max * c [j] -max * c [k]v [ i ]+v [ j ]+v [ k ]-m a x∗c [ i ]-m a x∗c [ j ]-m a x∗c [ k ] "enmax maxm a x , si x se supone que es grande, entoncesv [i] + v [j] + v [k] - x [c [i] - x [c [j] - x ∗ c [k] <0 v [ i] + v [j] + v [k] -x * c [i] -x * c [j] -x * c [k] <0v [ i ]+v [ j ]+v [ k ]-X∗c [ i ]-X∗c [ j ]-X∗c [ k ]<0 , sixxx se supone pequeño, entoncesv [i] + v [j] + v [k] - x ∗ c [i] - x ∗ c [j] - x ∗ c [k]> 0 v [i] + v [ j] + v [k] -x * c [i] -x * c [j] -x * c [k]> 0v [ i ]+v [ j ]+v [ k ]-X∗c [ i ]-X∗c [ j ]-X∗c [ k ]>0 . A partir de esto, pensé que esta pregunta podría transformarse en una búsqueda binaria: adivine el valor máximo en el rango de respuestas posibles, adivine la más grande, adivine la más pequeña, y adivine la más pequeña y adivine la más grande. Hasta que este número se acerque almáximo máximom a x está bien.
Código AC:
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e4+100;
int n,k;
double c[maxn],v[maxn];
bool check(double x){
double y[maxn];
for(int i=1;i<=n;i++){
y[i]=v[i]-x*c[i];
}
sort(y+1,y+n+1);
double s=0;
for(int i=n;i>n-k;i--){
//选择前k个最大y[i]累加,如果最大的累加和都小于0则这个数一定猜大了
s+=y[i];
}
return s>=0; //s>=0则表示猜小了。也即返回true时表示猜小了
}
int Bsearch(double l,double r){
int t=100; //猜100次就足以让答案满足“精确至整数”的精度。
while(t--){
double m=(l+r)/2;
if(check(m)) l=m; //猜小了就往大了猜
else r=m; //猜大了就往小了猜
}
return (int)l;
}
int main(){
int t;
cin>>t;
while(t--){
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>c[i]>>v[i];
}
double l=0;
double r=1e4; //大致估计答案在0-10000之间
cout<<Bsearch(l,r)<<endl;
}
return 0;
}