2015年7月2日
題目描述:輸入兩個整數n(1 <= n <= 10^5),w(1 <= w <= 10^9)。n表示有n個男孩和n個女孩,共2n個人;w表示有一個容器的盛有w毫升的水,然後第二行輸入2n整數arr[i](1 <= arr[i] <= 10^9),表示有2n個容器,第i個容器的容量是arr[i],讓後用着w毫升水在這2 * n個容器裏倒水,有兩個條件:倒出的水總容量小於等於w,每個男孩的杯子的盛水是n任意女孩的兩倍,求能倒出水最大容量是多少。
例如:
input
1 5
2 3
output
4.5
樣例解釋:有1個男孩,1個女孩,一個杯子的容量是2,一個杯子的容量是3,在容量大小爲2的杯子倒入1.5毫升的水,這個杯子被女孩佔用,另一個杯子的容量是3,倒入3毫升的水,總倒出的水是4.5毫升小於等於5毫升,並且女孩的水容量是男孩的一半。
題目很明確地說,每一個女生所盛的水是任意一個男生的一半,通過這個條件能夠得到一個結論:每個女生所盛的水是相同的,男生也是相同的,並且女生的所盛水的容量是男生的一半。
給了2n個杯子盛水。將這2n個杯子按容量的大小排序將arr[0]作爲女孩的基礎杯子容量,arr[n]作爲男孩的基礎杯子,將問題的規模抽象出來就是:
在[0,min(arr[0], arr[n] / 2)]中尋找一個值x,這個x是一個女孩的最終的容量,所以一個男孩的容量就是2x,這個x是屬於[0, arr[0]], 2x 屬於[0, arr[n]],並且要讓這個x儘量大,此時會想到的一個算法就是二分查找去搜索這個x。
應爲數據x有可能會是浮點數,所以比較的時候就會出現浮點數跟整數比較,直接用“==”比較是不合理的,是有精度遺失的,這裏的處理是用一個EPS來處理精度問題,a <= b可以等價轉化爲(b - a)>= EPS。這個EPS的精度要去多大是一個很不明確的值,有時取得過大是會出現精度損失,過小會比較耗時(即有可能會超時),據測試這裏取1e-11,1e-12是合理的。
#include <bits/stdc++.h>
#define MAXN 200007
#define EPS 1e-11 //精度問題一定要取合理,太小有誤差,太大會超時
using namespace std;
double arr[MAXN];
int main()
{
int n;
double w;
cin >> n >> w;
for(int i = 0; i < 2 * n; ++i)
scanf("%lf", &arr[i]);
sort(arr, arr + 2 * n);
double L = 0, R = min(arr[0], arr[n] / 2);
//在[0, min(arr[0], arr[n] / 2)]中二分搜索答案
while(fabs(R - L) > EPS)
{//當R - L大於EPS時就繼續找更優的值
double M = L + (R - L) / 2;
if((arr[n] - M * 2) >= EPS && (w - M * 3 * n) >= EPS) L = M;
//如果M是滿足條件的值,則試圖向右邊區間找更合理的答案
else R = M;
//否則在左邊的區間找更合理的答案
}
printf("%lf\n", L * 3 * n);
return 0;
}
轉載請註明出處:http://blog.csdn.net/royecode