[NOIP模擬賽]保證的利潤

題目描述
運氣是投注的基礎。有些人通過深入瞭解他們所投注的知識來提高機會和收益。 我們將採取不同的方法。
各種博彩公司爲同樣的結果提供不同的賠率或配額。(賠率x意味着如果你投注1歐元並正確預測結果,那麼你會收到x歐元。 如果你不正確地預測結果,你當然什麼都得不到。 請注意,不管結果如何,你都將支付1歐元。)是否可以通過巧妙地放置幾個賭注來確定賺取利潤呢? 你想要使這個保證的利潤儘可能的大。
我們想打賭的事件有兩個可能的結果。 有n個博彩公司提供不同的賠率。第i個博彩公司爲第一個結果提供的賠率爲ai,爲第二個結果提供的賠率爲bi。 
在任何一個博彩公司你都可以選擇下注或者是不下注。 你甚至可以在同一個博彩公司同時下注這兩個結果。 記住,所有的賭注必須是1歐元。但是你不能與同一個博彩公司多次下注相同的結果。

當第一個結果出現了,如果你在第i個博彩公司正好下注第一個結果,你就能從該公司獲得ai歐元。同理,當第二個結果出現了,如果你在第i個博彩公司正好下注第二個結果,你就能從該公司獲得bi歐元。當然,每一次下注都將花費1歐元。

如果你採用最佳的下注策略,那麼無論結果如何,你能得到的最大的保證利潤是多少呢?


輸入格式
第1行:1個整數n(1≤n≤100000),表示博彩公司的數量

接下來n行,每行2個浮點數ai和bi(1.0≤ai,bi≤1000.0),表示第i個博彩公司對兩個結果的賠率。每個浮點數最多4位十進制數。


輸出格式

第1行:1個浮點數,表示能夠取得的最大保證利潤。保留4位小數。


輸入樣例
4
1.4 3.7
1.2 2
1.6 1.4

1.9 1.5


輸出樣例

0.5000


樣例說明

最佳下注策略是在第一個博彩公司投注第二個結果,在第三和第四家博彩公司下注第一個結果。 這樣,當出現第一個結果,我們將獲得1.6 + 1.9-3 = 0.5。如果是第二個結果,我們將獲得3.7-3 = 0.7。所以我們保證有0.5歐元的利潤。



題解
設下注i家公司a結果,賠率和爲A;下注j家公司b結果,賠率和爲B;
要求利潤最大,那一定要下注儘量少的公司使得賠率儘量大,於是將a和b從大到小排序。
選擇時一定要保持A與B的值接近,因爲利潤爲max( min( A, B )-i-j ),若本來A<B,又去下注b結果使B增大,那麼當b結果未出現時,利潤會因A要多減而變小。


#include<cstdio>
#include<algorithm>
using namespace std;
const int N=200005;

int n;
double w, A, B, a[N], b[N];
bool cmp( double a, double b ) { return a>b; }

int main() {
	scanf( "%d", &n );
	for( int i=1; i<=n; i++ ) scanf( "%lf%lf", &a[i], &b[i] );
	sort( a+1, a+n+1, cmp );
	sort( b+1, b+n+1, cmp );
	for( int i=0, j=0; i<n || j<n; ) {
		if( A<B && i<n ) A+=a[++i];
		else if( j<n ) B+=b[++j];
		else break;
		w=max( w, min( A, B )-i-j );
	}
	printf( "%.4f\n", w );
	return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章