zoukankan      html  css  js  c++  java
  • 投票游戏

    题目大意:有 n 个人参加投票游戏。

    每个人会投支持票或者反对票,第 i 个人投支持票的概率是p[i] 。

    选出k个人使平票的概率最大。

    全部的输入数据满足:

    • 2kn,k是偶数。

    • 0pi1(1in)

    • n2000

    思路:根据样例我们可以发现先对所有的p[i]排序后,肯定是从头尾取几个人或者不取,这个性质或者说是推论可以用反证法证明(假定确定一部分人),f[i][j]事实上是关于p[i]的次数为1的函数。

    即最优选人方案一定是一部分前缀和一部分后缀组成的。

    这时候对于前缀和后缀都来一次dp(O(n^2))算出概率之后再枚举(O(n));

    所以得到复杂度应为O(n^2),这是肯定可以过的

    代码如下:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define maxn 2555
     4 int n,k;
     5 double p[maxn],a[maxn];
     6 double dp[maxn][maxn],f[maxn][maxn],ans=0;
     7 int main(){
     8 freopen("vote.in","r",stdin);
     9 freopen("vote.out","w",stdout);
    10 scanf("%d%d",&n,&k);
    11 for(int i=1;i<=n;i++)scanf("%lf",&p[i]);
    12 sort(p+1,p+n+1);
    13 for(int i=n-k+1;i<=n;i++)a[n+1-i]=p[i];
    14 dp[0][0]=f[0][0]=1.0;
    15 for(int i=1;i<=k;i++){
    16 for(int j=0;j<=i;j++){
    17 dp[i][j]=dp[i-1][j]*(1.0-p[i]);
    18 if(j>0)dp[i][j]+=dp[i-1][j-1]*p[i];
    19 f[i][j]=f[i-1][j]*(1.0-a[i]);
    20 if(j>0)f[i][j]+=f[i-1][j-1]*a[i];
    21 }
    22 }
    23 for(int i=0;i<=k;i++){
    24 double cnt=0;
    25 for(int j=0;j<=k/2;j++)cnt+=dp[i][j]*f[k-i][k/2-j];
    26 ans=max(ans,cnt);
    27 }
    28 printf("%.9f",ans);//看题目怎么说,我这里OJ交是要保留9位小数
    29 return 0;
    30 }
  • 相关阅读:
    0909 初识编译原理
    校园跳蚤市场-Sprint计划
    校园跳蚤市场
    5.2-5.3
    5.1封装
    阅读2
    汉堡包
    五章-问题
    结对子作业 四则运算 V2.0
    四则运算升级版
  • 原文地址:https://www.cnblogs.com/yjyl0098/p/13445538.html
Copyright © 2011-2022 走看看