c题: hdu6693
题意:给出n个买当前物品令人开心的概率值,问从中买1-n个,从购买的全部中选出一个使其开心的最大概率值。
题意很好理解,首先我们从什么入手,我们该怎么想这种题目,首先可以明确的一点是可以选一个,或者选两个,或者选3个,4个,。。。。n个的。
大的情况可以从小的情况中推理出来 ,
1: 首先如果选一个的话那么直接就选择最大的就可以了?
2: 如果选择两个, 不妨设置 pi<pj 则有 pi*(1-pj)+pj*(1-pi) 这是只开心一次的期望 那么就有 pi+pj-2*pi*pj 要选择两个,肯定是他能要变大才会选择。。。。
即 pi+pj-2*pi*pj> pj 有 pi -2*pi*pj >0 得到 pi*(1-2*pj) >0 得到pj<0.5 同理选3个,选4个的时候也要满足一下这样的原则。。。。。
3: 那选择多个的话怎么选择呢。这样选择的话很显然的话可以从两个看出, 设置pi<pk<pj<0.5 则有 pi*(1-pj) +pj*(1-pi) =pi+pj-2*pi*pj 有 pk+pj-2*pk*pj
则有 pk+pj-2*pk*pj -pi -pj +2*pi*pj = pk-pi -2pj(pk-pi)=(pk-pi)(1-2pj) >0 这样就说明选择越大的越好。。。。。。。。。
4:然后显然可以得到一个算法,先排好序,选择一个最大的,然后找到<=0.5的数的位置,从这个位置开始往前找,选一个,选两个,选3个,直到选完全部的时候即可。。。。。。。。。。
5: 然后这个列出一下公式保存一下即可,下面是代码。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <cmath> 5 #include <bitset> 6 #include <iostream> 7 typedef long long ll; 8 using namespace std; 9 const int maxn=10200; 10 int t,n; 11 double pi[maxn]; 12 int main(){ 13 scanf("%d",&t); 14 while(t--){ 15 scanf("%d",&n); 16 for(int i=1;i<=n;i++) scanf("%lf",&pi[i]); 17 sort(pi+1,pi+n+1); 18 int tip=0; 19 for(int i=1;i<=n;i++){ 20 if(pi[i]<=0.5){ 21 tip=i; 22 } 23 } 24 if(tip==0) printf("%.10lf\n",pi[n]); 25 else{ 26 double ans=pi[n]; 27 double p1=1.00-pi[tip],p2=pi[tip]; 28 for(int i=tip-1;i>=1;i--){ 29 ans=max(ans,pi[i]*p1+(1-pi[i])*p2); 30 p2=pi[i]*p1+(1-pi[i])*p2; 31 p1=p1*(1-pi[i]); 32 } 33 printf("%.10lf\n",ans); 34 } 35 } 36 return 0; 37 }