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

 

你可能感兴趣的:(codeforces)