【01 Planificación】POJ 2976 Pruebas de caída

POJ 2976 Pruebas de caída
Insertar descripción de la imagen aquíInsertar descripción de la imagen aquí

Significado de la pregunta: le otorga n puntajes basados ​​en puntos y le pide que les elimine k puntajes basados ​​en puntos para lograr Insertar descripción de la imagen aquí
este máximo
. Por ejemplo, dado 5/5, 0/1, 2/6, el puntaje promedio en este momento es Si
Insertar descripción de la imagen aquí
k=1, entonces puedes obtener El puntaje promedio máximo esInsertar descripción de la imagen aquí

Idea:
Después de estudiar la planificación 01 durante medio día, descubrí que cada uno de estos problemas se puede solucionar construyendo una función:
sea ∑ai/∑bi = l, luego ∑ai = l*∑bi, sea f(l) = ∑(ai - l*bi )
Cuando ∑ai / ∑bi ≥ l, es decir, cuando f(l)≥0, significa que hay una mejor solución.
La solución óptima se puede encontrar mediante bisección,

Actualice el límite:
simplemente encuentre el nk más grande con avidez. Si se satisface f (l) ≥ 0, significa que hay una mejor solución l = mid; de lo contrario: r = mid, (número de punto flotante dividido en dos)

#include  <map>
#include  <set>
#include  <cmath>
#include  <queue>
#include  <cstdio>
#include  <vector>
#include  <climits>
#include  <cstring>
#include  <cstdlib>
#include  <iostream>
#include  <algorithm>
using namespace std;
const int N=2e5+7;
double a[N],b[N];
int n,m;
double w[N];

int ok(double mid){
    
    
	double sum=0;
	for(int i=1;i<=n;i++){
    
    
		//w[i]=b[i]*mid-a[i];
		w[i]=a[i]-mid*b[i];
	}
	sort(w+1,w+1+n);
	for(int i=m+1;i<=n;i++){
    
    
		sum+=w[i];
	}
	return sum>=0;
}
int main(){
    
    
	
	while(cin>>n>>m){
    
    
		if(!n&&!m) return 0;
		for(int i=1;i<=n;i++) cin>>a[i];
		for(int i=1;i<=n;i++) cin>>b[i];
		double l=0.,r=1.;
		while(r-l>1e-6){
    
    
			double mid=(l+r)/2.;
			if(ok(mid)) l=mid;
			else r=mid;
		}
		printf("%.lf\n",l*100.);
	}
	return 0;
} 

Supongo que te gusta

Origin blog.csdn.net/weixin_51461002/article/details/124534639
Recomendado
Clasificación