zoukankan      html  css  js  c++  java
  • 【BZOJ】1778: [Usaco2010 Hol]Dotp 驱逐猪猡

    【题意】给定无向图,炸弹开始在1,在每个点爆炸概率Q=p/q,不爆炸则等概率往邻点走,求在每个点爆炸的概率。n<=300。

    【算法】概率+高斯消元

    【题解】很直接的会考虑假设每个点爆炸的概率,无法转移。每个点不爆炸的概率,也无法转移。

    因为爆炸概率相同,那么每个点爆炸的概率应该和到达该点的概率正相关。(另一种思路是和到达次数正相关)

    设f[x]表示炸弹到达点x的概率(之前不爆炸)。

    考虑枚举点x的下一步,发现无法用点y的概率来转移(因为f[y]可能由别的路走到)。

    考虑枚举点x的上一步,根据全概率公式P(A)=P(Bi)*P(A|Bi):

    $$f[x]=sum_{y}frac{f[y]*(1-Q)}{out[y]} , y ightarrow x$$

    理解:依赖于每一个可以到达x的点y,P(Bi)就是f[y],在到达y的前提下到达x的概率就是P(A|Bi)=(1-Q)/out[y]。

    (另一种理解,依赖于每一条可以到达x的边,P(Bi)=f[y]*(1-Q)/out[y],P(A|Bi)=1)

    特别的,点1还可以从天而降(概率为1),所以f[1]++

    最后ans[x]=f[x]*Q。或者根据炸弹最终爆炸概率为1,算Σf[i]后均分概率。

    此题还可以计算每个点到达的期望次数,也是正相关。

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const int maxn=310;
    long double a[maxn][maxn];
    int n,m,pp,qq,out[maxn];
    void gauss(){
        for(int i=1;i<n;i++){
            int r=i;
            for(int j=i+1;j<=n;j++)if(fabs(a[j][i])>fabs(a[r][i]))r=j;//////
            if(r!=i)for(int j=i;j<=n+1;j++)swap(a[r][j],a[i][j]);
            for(int j=i+1;j<=n;j++){
                for(int k=n+1;k>=i;k--){
                    a[j][k]-=a[j][i]/a[i][i]*a[i][k];
                }
            }
        }
        for(int i=n;i>=1;i--){
            for(int j=i+1;j<=n;j++)a[i][n+1]-=a[i][j]*a[j][n+1];
            a[i][n+1]/=a[i][i];
        }
    }
    int main(){
        
        int pp,qq;
        long double Q;
        scanf("%d%d%d%d",&n,&m,&pp,&qq);
        Q=1.0*pp/qq;
        for(int i=1;i<=m;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            a[v][u]+=(1-Q);
            if(u!=v)a[u][v]+=(1-Q);
            out[u]++;out[v]++;
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++)if(out[j])a[i][j]=a[i][j]/out[j];
            a[i][i]--;
        }
        a[1][n+1]=-1;
        gauss();
        for(int i=1;i<=n;i++)printf("%.9Lf
    ",a[i][n+1]*Q+(1e-13));///////////////
        return 0;
    }
    View Code

    注意:

    1.高斯消元过程中每次要找绝对值最大的主元,这是为了避免除零,提高精度。

    2.涉及负数的浮点数最后要避免-0,加eps

  • 相关阅读:
    ibatis 循环迭代
    javascript 中Table、TableCell 、TableRow对象
    Java重载Java构造器
    java垃圾回收机制
    Java在J2EE工程中路径寻址问题终极解决方案
    JAVASCRIPT 验证计算中英文混合字符串长度的解决
    java基础学习及总结
    ORACLE nvarchar2和varchar2的区别
    StringBuffer的用法
    关于Ant下的路径查找
  • 原文地址:https://www.cnblogs.com/onioncyc/p/7613829.html
Copyright © 2011-2022 走看看