Description
有一天Petya和他的朋友Vasya在进行他们众多旅行中的一次旅行,他们决定去参观一座城堡博物馆。这座博物馆有着特别的样式。它包含由m条走廊连接的n间房间,并且满足可以从任何一间房间到任何一间别的房间。
两个人在博物馆里逛了一会儿后两人决定分头行动,去看各自感兴趣的艺术品。他们约定在下午六点到一间房间会合。然而他们忘记了一件重要的事:他们并没有选好在哪儿碰面。等时间到六点,他们开始在博物馆里到处乱跑来找到对方(他们没法给对方打电话因为电话漫游费是很贵的)
不过,尽管他们到处乱跑,但他们还没有看完足够的艺术品,因此他们每个人采取如下的行动方法:每一分钟做决定往哪里走,有Pi 的概率在这分钟内不去其他地方(即呆在房间不动),有1-Pi 的概率他会在相邻的房间中等可能的选择一间并沿着走廊过去。这里的i指的是当期所在房间的序号。在古代建造是一件花费非常大的事,因此每条走廊会连接两个不同的房间,并且任意两个房间至多被一条走廊连接。
两个男孩同时行动。由于走廊很暗,两人不可能在走廊碰面,不过他们可以从走廊的两个方向通行。(此外,两个男孩可以同时地穿过同一条走廊却不会相遇)两个男孩按照上述方法行动直到他们碰面为止。更进一步地说,当两个人在某个时刻选择前往同一间房间,那么他们就会在那个房间相遇。
两个男孩现在分别处在a,b两个房间,求两人在每间房间相遇的概率。
题解:
还是这个套路, f[i][j] 表示一个人在i,另外一个在j的期望次数,为什么是期望次数呢?首先因为这样好推,然后因为两人在一个房间实际上只有一次,所以概率其实是等于期望次数的,然后分四种情况讨论:1、两个人都不动。2、两个人都动。3、a动b不动。4、a不动b动。注意在任何时候都不能从一个i,j相等的状态转移到当前的状态。然后我犯了个错误:理所当然的认为 f[a所在房间][b所在房间]=1+a留在原地概率∗b留在原地概率 ,结果错的一塌糊涂。其实就常规地推就好了,然后一开始的位置要+1。吐槽一下,一开始点开discuss,看错了,故意末尾没有空格,结果它居然有空格才能过?还没见过这样卡输出格式的。
代码:
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int Maxn=405;
const long double eps=1e-10;
int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
int n,m,p1,p2;
struct Edge{int x,y,next;}e[Maxn*Maxn];
int last[Maxn],len=0;
void ins(int x,int y)
{
int t=++len;
e[t].x=x;e[t].y=y;e[t].next=last[x];last[x]=t;
}
long double a[Maxn][Maxn],p[Maxn];
void gauss()
{
for(int i=1;i<=n*n;i++)
{
if(abs(a[i][i])<=eps)
{
for(int j=i+1;j<=n*n;j++)
if(abs(a[j][i])>eps)
{
for(int k=i;k<=n*n+1;k++)swap(a[j][k],a[i][k]);
break;
}
}
for(int j=i+1;j<=n*n;j++)
if(abs(a[j][i])>eps)
{
long double t=a[j][i]/a[i][i];
for(int k=i;k<=n*n+1;k++)a[j][k]-=t*a[i][k];
}
}
for(int i=n*n;i;i--)
{
for(int j=i+1;j<=n*n;j++)
a[i][n*n+1]-=a[i][j]*a[j][n*n+1];
a[i][n*n+1]/=a[i][i];
}
}
int degree[Maxn],num[Maxn][Maxn],cnt=0;
int main()
{
memset(a,0,sizeof(a));
n=read();m=read();p1=read();p2=read();
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=read(),y=read();
ins(x,y);ins(y,x);degree[x]++;degree[y]++;
}
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 o1=num[x1][x2];
a[o1][o1]=-1.0;
if(x1!=x2)a[o1][o1]+=p[x1]*p[x2];//两个都停在原地
for(int i=last[x1];i;i=e[i].next)
{int y1=e[i].y,o3=num[y1][x2];if(y1==x2)continue;a[o1][o3]+=(1.0-p[y1])*p[x2]/(long double)(degree[y1]);}
for(int j=last[x2];j;j=e[j].next)
{int y2=e[j].y,o2=num[x1][y2];if(x1==y2)continue;a[o1][o2]+=(1.0-p[y2])*p[x1]/(long double)(degree[y2]);}
for(int i=last[x1];i;i=e[i].next)
for(int j=last[x2];j;j=e[j].next)
{
int y1=e[i].y,y2=e[j].y,o4=num[y1][y2];
if(y1==y2)continue;
a[o1][o4]+=(1.0-p[y2])*(1.0-p[y1])/(long double)(degree[y1])/(long double)(degree[y2]);
}
}
a[num[p1][p2]][n*n+1]=-1.0;
gauss();
for(int i=1;i<=n;i++)printf("%.6Lf ",a[num[i][i]][n*n+1]);
}