概率计算: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 ",maxi); } return 0; }