zoukankan      html  css  js  c++  java
  • BZOJ 3270 && BZOJ 1778 (期望DP && 高斯消元)

    BZOJ 3270 :设置状态为Id(x,y)表示一人在x,一人在y这个状态的概率。 所以总共有n^2种状态。

    p[i]表示留在该点的概率,Out[i]=(1-p[i])/Degree[i]表示离开该点的概率.

    那么对于每一种状态a,b 则有P(a,b)=p[a]p[b]P(a,b)+Out[u]p[b]P(u,b)+p[a]Out[v]P(a,v)+Out[u]Out[v]P(u,v) 则有n^2个方程

    对于起始状态a,b,则有P(a,b)=p[a]p[b]P(a,b)+Out[u]p[b]P(u,b)+p[a]Out[v]P(a,v)+Out[u]Out[v]P(u,v)+1

     1  
     2 #include <cstdio>
     3 #include <cstring>
     4 const int Maxn=10010;
     5 double p[Maxn],Out[Maxn],a[510][510];
     6 int Degree[Maxn],n,m,head[Maxn],cnt,s,t,u,v;
     7 struct Edge{int to,next;}edge[Maxn<<1];
     8 inline void Add(int u,int v) 
     9 {edge[cnt].to=v;edge[cnt].next=head[u];head[u]=cnt++;}
    10 inline int Id(int x,int y) {return (x-1)*n+y;}
    11 inline void Swap(double &x,double &y) {double t=x;x=y;y=t;}
    12 void Build(int x,int y)
    13 {
    14     int S=Id(x,y); 
    15     a[S][S]-=1;
    16     for (int i=head[x];i!=-1;i=edge[i].next)
    17         for (int j=head[y];j!=-1;j=edge[j].next)
    18         {
    19             int u=edge[i].to,v=edge[j].to,T=Id(u,v);
    20             if (u!=v) 
    21             {
    22                 if (u==x && v==y) a[S][T]+=p[u]*p[v];
    23                 else if (u==x) a[S][T]+=p[u]*Out[v];
    24                 else if (v==y) a[S][T]+=Out[u]*p[v];
    25                 else a[S][T]+=Out[u]*Out[v];
    26             }
    27         }
    28 }
    29 inline void Guass(int n)
    30 {
    31     for (int i=1;i<=n;i++)
    32     {
    33         for (int j=i;j<=n;j++) 
    34             if (a[j][i])
    35             {
    36                 for (int k=1;k<=n+1;k++) Swap(a[i][k],a[j][k]);
    37                 for (int k=1;k<=n+1;k++) if (k!=i) a[i][k]/=a[i][i];
    38                 a[i][i]=1;
    39                 break;
    40             }
    41         if (!a[i][i]) continue;
    42         for (int j=1;j<=n;j++) 
    43         {
    44             if (j==i) continue;
    45             double t=a[j][i];
    46             for (int k=1;k<=n+1;k++) a[j][k]-=t*a[i][k];
    47         }
    48     }
    49 }
    50 int main()
    51 {
    52     scanf("%d%d%d%d",&n,&m,&s,&t);
    53     memset(head,-1,sizeof(head));
    54     for (int i=1;i<=m;i++)
    55     {
    56         scanf("%d%d",&u,&v);
    57         Add(u,v),Add(v,u);
    58         Degree[u]++,Degree[v]++;
    59     }
    60     for (int i=1;i<=n;i++) scanf("%lf",&p[i]);
    61     for (int i=1;i<=n;i++) Out[i]=(1-p[i])/Degree[i];
    62     for (int i=1;i<=n;i++) Add(i,i);
    63     for (int i=1;i<=n;i++)
    64         for (int j=1;j<=n;j++) Build(i,j);
    65     a[Id(s,t)][n*n+1]=-1;
    66     Guass(n*n);
    67     for (int i=1;i<=n;i++) printf("%.6lf ",a[Id(i,i)][n*n+1]);
    68     return 0;
    69 }
    C++

     BZOJ 1778:和上面的题目差不多但是要注意的是自己不可能转移到自己因为要么炸要么移动

    P(u)=Out(v)*P(v) 特别的 P(1)=Out(v)*P(v)+P/Q然后高斯消元即可.

     1 #include <cstdio>
     2 #include <cmath>
     3 #include <cstring>
     4 #define LD long double
     5 const int Maxn=510;
     6 const int Maxm=50100;
     7 const LD eps=1e-13;
     8 int Degree[Maxn],head[Maxn],n,m,P,Q,cnt,u,v;
     9 LD a[Maxn][Maxn],t,Out[Maxn];
    10 struct  Edge{int to,next;}edge[Maxm<<2];
    11 inline void Swap(LD &x,LD &y) {LD t=x;x=y;y=t;}
    12 inline int dcmp(LD x) {if (fabs(x)<eps) return 0; return (x>0)?1:-1;}
    13 inline void Add(int u,int v)
    14 {edge[cnt].to=v;edge[cnt].next=head[u];head[u]=cnt++;}
    15 inline void Build(int u)
    16 {
    17     a[u][u]=1.0;
    18     for (int i=head[u];i!=-1;i=edge[i].next)
    19         a[u][edge[i].to]=-Out[edge[i].to];
    20 }
    21 inline void Gauss()
    22 {
    23     for (int i=1;i<=n;i++)
    24     {
    25         for (int j=i;j<=n;j++) 
    26             if (dcmp(a[i][j])!=0)
    27             {
    28                 for (int k=1;k<=n+1;k++) Swap(a[i][k],a[j][k]);
    29                 for (int k=1;k<=n+1;k++) if (k!=i) a[i][k]/=a[i][i];
    30                 a[i][i]=1;
    31                 break;
    32             }
    33         if (dcmp(a[i][i])==0) continue;
    34         for (int j=1;j<=n;j++) 
    35         {
    36             if (j==i) continue;
    37             LD t=a[j][i];
    38             for (int k=1;k<=n+1;k++) a[j][k]-=t*a[i][k];
    39         }
    40     }
    41 }
    42 int main()
    43 {
    44     scanf("%d%d%d%d",&n,&m,&P,&Q); t=(LD)P/(LD)Q; t=1.0-t;
    45     memset(head,-1,sizeof(head)); cnt=0;
    46     for (int i=1;i<=m;i++) 
    47     {
    48         scanf("%d%d",&u,&v);
    49         Add(u,v),Add(v,u),Degree[u]++,Degree[v]++;
    50     }
    51       
    52     for (int i=1;i<=n;i++) Out[i]=t/(LD)Degree[i];
    53     for (int i=1;i<=n;i++) Build(i);
    54     a[1][n+1]=1-t;
    55     Gauss();
    56     for (int i=1;i<=n;i++) printf("%.9Lf
    ",a[i][n+1]);
    57     return 0;
    58 }
    C++
  • 相关阅读:
    php 中的 Output Control 函数
    web安全知识
    php写一个web五子棋
    实现一个web服务器, 支持php
    字节序
    TinyHTTPd源码分析
    linux 管道通信
    linux网络编程
    微信公众号开发-静默授权实现消息推送(微服务方式)
    初学 Nginx
  • 原文地址:https://www.cnblogs.com/yyjxx2010xyu/p/5702765.html
Copyright © 2011-2022 走看看