BZOJ3270 博物馆(高斯消元+概率期望)

  将两个人各自所在点视为状态,新建一个图。到达某个终点的概率等于其期望次数。那么高斯消元即可。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
#define N 410
int n,m,s,t,d[21][21],degree[21];
double a[N][N],p[21];
int trans(int x,int y){return (x-1)*n+y;}
void gauss()
{
    for (int i=1;i<n*n;i++)
    {
        int mx=i;
        for (int j=i+1;j<=n*n;j++)
        if (fabs(a[j][i])>fabs(a[mx][i])) mx=j;
        if (mx!=i) swap(a[i],a[mx]);
        for (int j=i+1;j<=n*n;j++)
        {
            double t=a[j][i]/a[i][i];
            for (int k=i;k<=n*n+1;k++)
            a[j][k]-=t*a[i][k];
        }
    }
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("bzoj3270.in","r",stdin);
    freopen("bzoj3270.out","w",stdout);
    const char LL[]="%I64d
";
#else
    const char LL[]="%lld
";
#endif
    n=read(),m=read(),s=read(),t=read();
    for (int i=1;i<=m;i++)
    {
        int x=read(),y=read();
        degree[x]++,degree[y]++;
        d[x][y]=d[y][x]=1;
    }
    for (int i=1;i<=n;i++) d[i][i]=1;
    for (int i=1;i<=n;i++) cin>>p[i];
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
            for (int x=1;x<=n;x++)
                for (int y=1;y<=n;y++)
                if (x!=y&&d[x][i]&&d[y][j])
                {
                    if (x==i) a[trans(i,j)][trans(x,y)]=p[x];
                    else if (d[x][i]) a[trans(i,j)][trans(x,y)]=(1-p[x])/degree[x];
                    if (y==j) a[trans(i,j)][trans(x,y)]*=p[y];
                    else if (d[y][j]) a[trans(i,j)][trans(x,y)]*=(1-p[y])/degree[y];
                }
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
        a[trans(i,j)][trans(i,j)]--;
    a[trans(s,t)][n*n+1]=-1;
    gauss();
    for (int i=n*n;i>=1;i--)
    {
        a[i][n*n+1]/=a[i][i];
        for (int j=i-1;j;j--)
        a[j][n*n+1]-=a[i][n*n+1]*a[j][i];
    }
    for (int i=1;i<=n;i++) printf("%.6lf ",a[trans(i,i)][n*n+1]);
    return 0;
}
原文地址:https://www.cnblogs.com/Gloid/p/9677927.html