zoukankan      html  css  js  c++  java
  • [BZOJ3150][Ctsc2013]猴子 期望dp+高斯消元

    3150: [Ctsc2013]猴子

    Time Limit: 20 Sec  Memory Limit: 256 MBSec  Special Judge
    Submit: 163  Solved: 105
    [Submit][Status][Discuss]

    Description

    小Q和小M最近发明了一种卡牌游戏,叫猴子大战。游戏最初小Q和小M各会取得一部分猴子牌。每局游戏,他们两个
    需要分别等概率地从自己的猴子牌中抽取一张进行战斗。获胜的一方将获得双方的猴子牌。如果一方获得了所有的
    猴子牌,则该方获得整场游戏的胜利。否则游戏将一直进行下去。 在进行了若干场比赛以后,小Q和小M算出了一
    张胜率表,为每张猴子牌之间进行战斗双方获胜的概率。由于每场战斗一定会决出胜负,而且胜率不受先后顺序的
    影响,因此对于任意的两张猴子牌A和B,A战胜B的概率加B战胜A的概率为1。 由于自己老是输给小M,小Q开始怀疑
    自己每次拿到的猴子牌是否能获得胜利。他希望求出自己拿到的每种猴子牌组合的获胜的概率。 由于小Q接下来还
    有在CD市体育中心数以万计的运动计划,因此这个问题只能交给你来解决了。

    Input

    输入的第一行包含两个正整数n和m,表示猴子牌的总张数和需要求的猴子牌组合的个数。 
    接下来有n行,每行包含n个实数,每个实数保留了两位小数。
    这n行中,其中第i行第j列的数为Pi,j,表示第i张猴子牌战胜第j张猴子牌的概率。
    保证Pi,j + Pj,i  =  1。特别地,Pi,j = 0.5,没有特殊意义。 最后又m行。
    每行包含一个长度为n的无空格分隔的01串,表示一个猴子牌的组合。
    其中第i个字符如果为0,表示最初第i张牌在小M处,否则表示在小Q处。

    Output

    输出m行,每行一个实数,四舍五入保留八位小数(请强制输出八位浮点数),
    一次表示每个给定的猴子牌组合下小Q获胜的概率。

    Sample Input

    3 4
    0.50 0.60 0.40
    0.40 0.50 0.70
    0.60 0.30 0.50
    110
    011
    111
    000

    Sample Output

    0.71304348
    0.66086957
    1.00000000
    0.00000000

    HINT

    【评分方法】 

    你的答案的每一行如果与我们给定的参考答案的差别均不超过2×10-6,则获得该测试点的得分,否则不得分。 

    参考答案保证与真实值的差别不超过10-8,因此如果你输出的答案保证与真实值差别不超过2×10^-6 — 2×10^-8,才能保证正确。

    Source

    vfleaking提供spj

    首先可以想到设f[S]表示手牌集合为S时的胜利期望。

    这样显然是过不了的。

    这时我们发现如果A∩B=ø则f[AυB]=f[A]+f[B]

    因此我们可以设f[i]表示手牌为i的胜利期望。

    运用高斯消元求解即可。

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #include<cstdio>
     5 #include<cmath>
     6 #include<algorithm>
     7 using namespace std;
     8 double f[105][105],a[105][105];
     9 int n,m;char s[105];
    10 int main() {
    11     scanf("%d%d",&n,&m);
    12     for(int i=1;i<n;i++) {
    13         a[i][i]=1-n;
    14         for(int j=1;j<=n;j++) {
    15             double tmp;scanf("%lf",&tmp);
    16             if(i!=j) {
    17                 a[i][j]=tmp;a[i][i]+=tmp;
    18             }
    19         }
    20     }
    21     for(int i=1;i<=n;i++) {
    22         double tmp;scanf("%lf",&tmp);
    23         a[n][i]=1;
    24     }
    25     a[n][n+1]=1;
    26     for(int i=1;i<=n;i++) {
    27         int tmp=i;
    28         for(int j=i;j<=n;j++) {
    29             if(fabs(a[j][i])>=1e-9) {tmp=j;break;}
    30         }
    31         if(tmp!=i) swap(a[tmp],a[i]);
    32         for(int j=i+1;j<=n;j++) {
    33             double chg=a[j][i]/a[i][i];
    34             for(int k=i;k<=n;k++) {
    35                 a[j][k]-=a[i][k]*chg;
    36             }
    37         }
    38     }
    39     for(int i=n;i>=1;i--) {
    40         for(int j=i+1;j<=n;j++) a[i][n+1]-=a[i][j]*a[j][n+1];
    41         a[i][n+1]/=a[i][i];
    42     }
    43     while(m--) {
    44         scanf("%s",s+1);double ans=0;
    45         for(int i=1;i<=n;i++) {
    46             if(s[i]=='1') ans+=a[i][n+1];
    47         }
    48         printf("%.8lf
    ",ans);
    49     }
    50 }
    View Code
  • 相关阅读:
    今日总结
    今日总结
    今日总结
    今日总结
    今日总结
    java自学
    java自学
    Java自学
    Java自学
    java自学
  • 原文地址:https://www.cnblogs.com/wls001/p/10112518.html
Copyright © 2011-2022 走看看