• BZOJ 3270 博物馆 && CodeForces 113D. Museum 期望概率dp 高斯消元


    大前提,把两个点的组合看成一种状态 x

    两种思路 O(n^7) f[x]表示在某一个点的前提下,这个状态经过那个点的概率,用相邻的点转移状态,高斯一波就好了

                   O(n^6) 想象成臭气弹,这个和那个的区别只是状态维数变化,f[x]表示这个状态出现的概率,高斯一下就好了

    我比较傻只想出来O(n^7)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    typedef double D;
    D a[400][400],source[400][400],ans[50],keep[50],get[500],sz;
    int via[50][50],need,map[400000];
    int n,m,Petya,Vasya;
    inline int hash(int x,int y)
    {
      if(x>y)x^=y^=x^=y;
      int gg=x*100+y;
      if(map[gg]==0)map[gg]=++sz;
      return map[gg];
    }
    inline D abs(D x)
    {
      return x<0.0?0.0-x:x;
    }
    void gause()
    {
        for(int i=1,k=1;i<=need&&k<=need;i++,k++)
        {
           int temp=i;
           D h=abs(a[i][k]);
           for(int j=i+1;j<=need;j++)
           if(h<abs(a[j][k]))
           {
             temp=j;
             h=abs(a[j][k]);
           }
           if(temp!=i)
           {
             for(int j=k;j<=need+1;j++)
              swap(a[i][j],a[temp][j]);
           }
           for(int j=i+1;j<=need;j++)
           {
              h=a[j][k]/a[i][k];
              for(int l=k;l<=need+1;l++)
               a[j][l]-=h*a[i][l];
           }
        }
        for(int i=need;i>0;i--)
        {
          for(int j=i+1;j<=need;j++)
            a[i][need+1]-=a[i][j]*get[j];
          get[i]=a[i][need+1]/a[i][i];
        }
    }
    void blabla(int x)
    {
      for(int i=0;i<400;i++)
       for(int j=0;j<400;j++)
        a[i][j]=source[i][j];
      a[hash(x,x)][need+1]=1.0;
      gause();
      ans[x]=get[hash(Petya,Vasya)];
    }
    void pre()
    {
        scanf("%d%d%d%d",&n,&m,&Petya,&Vasya);
        for(int i=1;i<=m;i++)
        {
          int x,y;
          scanf("%d%d",&x,&y);
          via[x][++via[x][0]]=y;
          via[y][++via[y][0]]=x;
        }
        need=n*(n+1)/2;
        for(int i=1;i<=n;i++)
         scanf("%lf",&keep[i]);
        for(int i=1;i<=n;i++)
         for(int j=i;j<=n;j++)
         {
           int x=hash(i,j);
           if(i==j)
           {
              source[x][x]=1.0;
              continue;
           }
           D Viai=1.0*via[i][0],Viaj=1.0*via[j][0];
           D Keep=(1.0-keep[i])*(1.0-keep[j])/Viai/Viaj;
           for(int z=1;z<=via[i][0];z++)
            for(int y=1;y<=via[j][0];y++)
             source[x][hash(via[i][z],via[j][y])]+=Keep;
           Keep=(1.0-keep[i])*keep[j]/Viai;
           for(int z=1;z<=via[i][0];z++)
             source[x][hash(via[i][z],j)]+=Keep;
           Keep=(1.0-keep[j])*keep[i]/Viaj;
           for(int y=1;y<=via[j][0];y++)
             source[x][hash(via[j][y],i)]+=Keep;
           source[x][x]+=keep[i]*keep[j];
           source[x][x]-=1.0;
         }
    }
    void work()
    {
        ans[n]=1.0;
        for(int i=1;i<n;i++)
        {
         blabla(i);
         ans[n]-=ans[i];
        }
    }
    void print()
    {
        for(int i=1;i<=n;i++)
         printf("%.10lf ",ans[i]);
    }
    int main()
    {
        pre();
        work();
        print();
    }
  • 相关阅读:
    P1363-幻象迷宫
    P1582-倒水
    P2123-皇后游戏
    P1233-木棍加工
    P1052-过河
    P1541-乌龟棋
    P1736-创意吃鱼法
    P1417-烹调方案
    LeetCode--043--字符串相乘(java)
    LeetCode--041--缺失的第一个整数(java)
  • 原文地址:https://www.cnblogs.com/TSHugh/p/7088182.html
Copyright © 2020-2023  润新知