• 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++
  • 相关阅读:
    03 在百度地图上定位到指定位置
    01 如何将百度地图加入IOS应用程序?
    三个字理解委托机制
    iOS 应用程序打包、真机调试 方法
    在读iOS官方文档时,里面有很多你不懂的单词,不要担心
    用“大控件”与“大数据类型”思想来理解view Cotroller
    04 将当前位置用大头针标注到百度地图上
    02 使用百度地图获得当前位置的经纬度
    专注分享思考过程
    像孙正义为了练英语坚决不说日语一样。我也应该有坚决不看中文文档的心!
  • 原文地址:https://www.cnblogs.com/yyjxx2010xyu/p/5702765.html
Copyright © 2020-2023  润新知