poj 2976 Pruebas de caída (programación fraccionada 0/1)

Límite de tiempo:  1000 MS Límite de memoria:  65536K
Envíos totales:  31958 Aceptado:  10375

Descripción

En un curso determinado, realizas  n  exámenes. Si obtiene  ai  de  las preguntas bi  correctas en la prueba  i , su promedio acumulado se define como

.

Dados los puntajes de sus exámenes y un entero positivo  k , determine qué tan alto puede llegar a su promedio acumulativo si se le permite reducir cualquier  k  de los puntajes de sus exámenes.

Suponga que realiza 3 pruebas con puntuaciones de 5/5, 0/1 y 2/6. Sin abandonar ninguna prueba, su promedio acumulado es 

. Sin embargo, si abandona la tercera prueba, su promedio acumulado se convierte en .

Aporte

El archivo de prueba de entrada contendrá varios casos de prueba, cada uno con exactamente tres líneas. La primera línea contiene dos números enteros, 1 ≤  n  ≤ 1000 y 0 ≤  k  <  n . La segunda línea contiene  n  números enteros que indican  ai  para todo  i . La tercera línea contiene  n  enteros positivos que indican  bi  para todo  i . Se garantiza que 0 ≤  ai  ≤  bi  ≤ 1.000.000.000. El final del archivo está marcado por un caso de prueba con  n  =  k  = 0 y no debe procesarse.

Producción

Para cada caso de prueba, escriba una sola línea con el promedio acumulativo más alto posible después de descartar  k  de los puntajes de la prueba dados. El promedio debe redondearse al número entero más cercano.

Entrada de muestra

3 1
5 0 2
5 1 6
4 2
1 2 7 9
5 6 7 9
0 0

Salida de muestra

83
100

Pista

Para evitar ambigüedades debidas a errores de redondeo, las pruebas de los jueces se han construido de modo que todas las respuestas estén al menos a 0,001 de un límite de decisión (es decir, se puede suponer que el promedio nunca es 83,4997).

Ideas:

en tema

 Para simplificar, intenta encontrar la x que sea menor que .

El punto final izquierdo es 0 y el punto final derecho es la suma acumulativa de ai. Esta es una búsqueda binaria eficiente.

Al realizar la dicotomía, también es necesario considerar si es monótona.

#include<stdio.h>
#include<algorithm>
#include<iostream>
using namespace std;
struct Pair {
	int a, b;
	double y;
}p[1005];
bool cmp(Pair a, Pair b) {
	return a.y > b.y; // 从大到小
}
int n, k;
bool check(double x) {
	for (int i = 0; i < n; i++) {
		p[i].y = p[i].a * 1.0 - x * p[i].b; // y = a - x*b  在x轴小点的值
	}
	sort(p, p + n, cmp);
	double f = 0;
	for (int i = 0; i < k; i++) f += p[i].y;
	return f < 0;
}
int main() {
	while (cin >> n >> k, n + k) {
		k = n - k; // 选出 k 对
		for (int i = 0; i < n; i++) cin >> p[i].a;
		for (int i = 0; i < n; i++) cin >> p[i].b;
		double L = 0, R = 0;
		for (int i = 0; i < n; i++)	R += p[i].a;
		for (int i = 0; i < 50; i++) {
			double mid = L + (R - L) / 2;
			if (check(mid)) R = mid;
			else L = mid;
		}
		printf("%d\n", (int)(100 * (L + 0.005)));
	}
	return 0;
}

Supongo que te gusta

Origin blog.csdn.net/zhi6fui/article/details/128616271
Recomendado
Clasificación