Fork me on GitHub

Codeforces Round #253 Div2 D.Andrey and Problem 概率+贪心

概率计算:P(某set) = 

令:  和  

现在考虑:

1.考虑某个集合,再加一个概率为Pi的朋友后能不能使总概率提高。

即: 由公式可知, 如果 S < 1,则delta > 0,则可以加入这个朋友。

 

2.如果要加一个朋友有两个候选的,其概率分别为Pi,Pj,(设Pi < Pj)那么加哪个会更优呢?

Δi - Δj = P·pi·(1 - S) - P·pj·(1 - S) = P·(1 - S)·(pi - pj) > 0.  如果 S < 1 那么 pi > pj 时可以使 Δi - Δj  > 0,即P较大的那个带来的价值更高,所以优先选P大的那个。虽然这个

只是局部更优,但是用反证法可以证明是全局最优的。

 

所以由上述分析,以概率从大到小的方式逐步加入元素,因为由1,很可能S<1,即可能加一个会更优,所以我们逐步加入,又由2,优先加最大的,所以从大到小加入能保证最优。

然后每加入一个都计算该种情况下的总概率,更新答案。

 

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#define Mod 1000000007
using namespace std;
#define N 1000007

double a[104];
std::vector<double> v;

double calc(vector<double> v)
{
    int len = v.size();
    int i,j;
    double res = 0.0;
    for(i=0;i<len;i++)
    {
        double tmp = v[i];
        for(j=0;j<len;j++)
        {
            if(i == j)
                continue;
            tmp *= (1-v[j]);
        }
        res += tmp;
    }
    return res;
}

int main()
{
    int n,i,j;
    while(scanf("%d",&n)!=EOF)
    {
        double maxi = -1.0;
        for(i=0;i<n;i++)
            scanf("%lf",&a[i]);
        sort(a,a+n);
        v.clear();
        for(i=n-1;i>=0;i--)
        {
            v.push_back(a[i]);
            maxi = max(calc(v),maxi);
        }
        printf("%.10lf\n",maxi);
    }
    return 0;
}
View Code

 

posted @ 2014-06-20 18:17  whatbeg  阅读(223)  评论(0编辑  收藏  举报