zoukankan      html  css  js  c++  java
  • [bzoj3270] 博物馆

    题目传送门

    读入边的时候记录每个点的度d。

    设f[x][y]为从开始到一个人在x,一个人在y的概率。

    f[x][y]可以通过四种状态转移过来。

    1.两个人都原地不动:通过f[x][y]自己转移过来,概率为p[x]*p[y]。

    2.第一个人不动,第二个人从j过来(j和y有连边):通过f[x][j]转移,概率为p[x]*(1-p[j])/d[j]。

    3.第二个人不动,第一个人从i过来(i和x有连边):通过f[i][y]转移,概率为p[y]*(1-p[i])/d[i]。

    4.第一个人从i过来,第二个人从j过来(i与x、j与y均有连边):通过f[i][j]转移,概率为(1-p[i])*(1-p[j])*(d[i]*d[j])。

    这样我们得到了状态转移方程。

    可以看出任意两种状态(x,y)之间都能转移(没有连边的概率为0),只是概率不同。

    这样总共n*n个状态,每个状态都得到一个方程,每个方程包含n*n个未知数。

    上高斯消元求解。

    最后对于x==y的状态进行输出。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 
     6 int n,s,m,a,b;
     7 int e[25][25];
     8 int d[25];
     9 double ps[25];
    10 double k[405][405];
    11 double ans[405];
    12 
    13 int id(int x,int y)
    14 {
    15     return x*n-n+y;
    16 }
    17 
    18 double v(double rw)
    19 {
    20     return rw>0?rw:(-rw);
    21 }
    22 
    23 void cal(int x,int y)
    24 {
    25     int p=id(x,y);
    26     k[p][p]=-1.00;
    27     for(int i=1;i<=n;i++)
    28     {
    29         if(!e[i][x])continue;
    30         for(int j=1;j<=n;j++)
    31         {
    32             if((!e[j][y])||(i==j))continue;
    33             int q=id(i,j);
    34             if(p==q)k[p][q]+=ps[i]*ps[j];
    35             else if(x==i)k[p][q]+=ps[i]*(1.0-ps[j])/(double)d[j];
    36             else if(y==j)k[p][q]+=ps[j]*(1.0-ps[i])/(double)d[i];
    37             else k[p][q]+=(1.0-ps[i])*(1.0-ps[j])/(double)(d[i]*d[j]);
    38         }
    39     }
    40 }
    41 
    42 void gauss()
    43 {
    44     for(int i=1;i<=s;i++)
    45     {
    46         int p=i;
    47         for(int j=i+1;j<=s;j++)
    48             if(v(k[j][i])>v(k[p][i]))p=j;
    49         if(p!=i)
    50             for(int j=i;j<=s+1;j++)
    51                 swap(k[p][j],k[i][j]);
    52         double div=k[i][i];
    53         for(int j=i;j<=s+1;j++)k[i][j]/=div;
    54         for(int j=i+1;j<=s;j++)
    55         {
    56             div=k[j][i];
    57             for(int l=i;l<=s+1;l++)
    58                 k[j][l]-=k[i][l]*div;
    59         }
    60     }
    61     ans[s]=k[s][s+1];
    62     for(int i=s-1;i;i--)
    63     {
    64         ans[i]=k[i][s+1];
    65         for(int j=i+1;j<=s;j++)
    66             ans[i]-=k[i][j]*ans[j];
    67     }
    68 }
    69 
    70 int main()
    71 {
    72     scanf("%d%d%d%d",&n,&m,&a,&b);
    73     s=n*n;
    74     for(int i=1;i<=m;i++)
    75     {
    76         int ff,tt;
    77         scanf("%d%d",&ff,&tt);
    78         e[ff][tt]=e[tt][ff]=1;
    79         d[ff]++;d[tt]++;
    80     }
    81     for(int i=1;i<=n;i++)scanf("%lf",&ps[i]),e[i][i]=1;
    82     k[id(a,b)][s+1]=-1.00;
    83     for(int i=1;i<=n;i++)
    84         for(int j=1;j<=n;j++)
    85             cal(i,j);
    86     gauss();
    87     for(int i=1;i<=n;i++)printf("%.6lf ",ans[id(i,i)]);
    88     return 0;
    89 }
  • 相关阅读:
    flex设置成1和auto有什么区别
    在SUBLIME TEXT中安装SUBLIMELINTER进行JS&CSS代码校验
    gulp教程之gulp-less
    sublime注释插件与javascript注释规范
    移动端尺寸基础知识
    webpack入门教程
    IO中同步、异步与阻塞、非阻塞的区别
    Node.js的线程和进程
    Cocos2d-x 3.0中 物理碰撞检測中onContactBegin回调函数不响应问题
    hdu 1789 Doing Homework again 贪心
  • 原文地址:https://www.cnblogs.com/cervusy/p/9720276.html
Copyright © 2011-2022 走看看