3270: 博物馆

题意:

两个人在图上走,每个点有 pi p i 的概率留在原地,其它等概率去一个相邻的点,直到相遇为止。问在每个点相遇的概率。

题意:

等价于求到某个点的期望值。
f[i][j] f [ i ] [ j ] 表示一个人在i一个人在j的次数的期望值,然后列出转移方程,高斯消元即可。
注意不能从 i=j i = j 的点转移过来,因为已经停止了。
code:

#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;
int n,m,A,B,deg[25];
long double p[25];
struct node{
    int y,next;
}a[450];int len=0,last[25];
long double g[410][410];
void ins(int x,int y)
{
    a[++len].y=y;
    a[len].next=last[x];last[x]=len;
}
int num[25][25];
const long double eps=1e-10;
void guass()
{
    for(int i=1;i<=n*n;i++)
    {
        if(abs(g[i][i])<=eps)
        {
            for(int j=i+1;j<=n*n;j++)
                if(abs(g[j][i])>eps)
                {
                    for(int k=1;k<=n*n;k++) swap(g[i][k],g[j][k]);
                    break;
                }
        }
        for(int j=i+1;j<=n*n;j++)
            if(abs(g[j][i])>eps)
            {
                long double t=g[j][i]/g[i][i];
                for(int k=i;k<=n*n+1;k++) g[j][k]-=t*g[i][k];
            }
    }
    for(int i=n*n;i>=1;i--)
    {
        for(int j=i+1;j<=n*n;j++)
            g[i][n*n+1]-=g[i][j]*g[j][n*n+1];
        g[i][n*n+1]/=g[i][i];
    }
}
int cnt=0;
int main()
{
    scanf("%d %d %d %d",&n,&m,&A,&B);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            num[i][j]=++cnt;
    for(int i=1;i<=m;i++)
    {
        int x,y;scanf("%d %d",&x,&y);
        deg[x]++;deg[y]++;ins(x,y);ins(y,x);
    }
    for(int i=1;i<=n;i++) scanf("%Lf",&p[i]);
    for(int x1=1;x1<=n;x1++)
        for(int x2=1;x2<=n;x2++)
        {
            int s1=num[x1][x2];
            g[s1][s1]=-1.0;
            if(x1!=x2) g[s1][s1]+=p[x1]*p[x2];//两个都停在原地
            for(int i=last[x1];i;i=a[i].next)
            {
                int y1=a[i].y,s3=num[y1][x2];
                if(y1==x2) continue;
                g[s1][s3]+=(1.0-p[y1])*p[x2]/(long double)(deg[y1]);
            }
            for(int j=last[x2];j;j=a[j].next)
            {
                int y2=a[j].y,s2=num[x1][y2];
                if(x1==y2) continue;
                g[s1][s2]+=(1.0-p[y2])*p[x1]/(long double)(deg[y2]);
            }
            for(int i=last[x1];i;i=a[i].next)
                for(int j=last[x2];j;j=a[j].next)
                {
                    int y1=a[i].y,y2=a[j].y,s4=num[y1][y2];
                    if(y1==y2) continue;
                    g[s1][s4]+=(1.0-p[y2])*(1.0-p[y1])/(long double)(deg[y1])/(double)(deg[y2]);
                }
        }
    g[num[A][B]][n*n+1]=-1.0;
    guass();
    for(int i=1;i<=n;i++) printf("%.6Lf ",g[num[i][i]][n*n+1]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值