zoukankan      html  css  js  c++  java
  • bzoj 3270: 博物馆

    Description

    有一天Petya和他的朋友Vasya在进行他们众多旅行中的一次旅行,他们决定去参观一座城堡博物馆。这座博物馆有着特别的样式。它包含由m条走廊连接的n间房间,并且满足可以从任何一间房间到任何一间别的房间。
    两个人在博物馆里逛了一会儿后两人决定分头行动,去看各自感兴趣的艺术品。他们约定在下午六点到一间房间会合。然而他们忘记了一件重要的事:他们并没有选好在哪儿碰面。等时间到六点,他们开始在博物馆里到处乱跑来找到对方(他们没法给对方打电话因为电话漫游费是很贵的)
    不过,尽管他们到处乱跑,但他们还没有看完足够的艺术品,因此他们每个人采取如下的行动方法:每一分钟做决定往哪里走,有Pi 的概率在这分钟内不去其他地方(即呆在房间不动),有1-Pi 的概率他会在相邻的房间中等可能的选择一间并沿着走廊过去。这里的i指的是当期所在房间的序号。在古代建造是一件花费非常大的事,因此每条走廊会连接两个不同的房间,并且任意两个房间至多被一条走廊连接。
    两个男孩同时行动。由于走廊很暗,两人不可能在走廊碰面,不过他们可以从走廊的两个方向通行。(此外,两个男孩可以同时地穿过同一条走廊却不会相遇)两个男孩按照上述方法行动直到他们碰面为止。更进一步地说,当两个人在某个时刻选择前往同一间房间,那么他们就会在那个房间相遇。
    两个男孩现在分别处在a,b两个房间,求两人在每间房间相遇的概率。

    Solution

    与游走一题差不多,只需要同时记录两个人的位置即可
    (f[x][y]) 表示两个人分别在 (x),(y) 这个点的期望次数,因为经过次数的期望=经过的概率*次数
    并且因为 (f[x][x]) 为终止状态,所以次数为 (1) ,所以这种情况下概率等于期望
    对于DP:
    ((x,y)->(x,u)),((x,y)->(v,y)),((x,y)->(v,u)) 三种情况讨论即可

    #include<bits/stdc++.h>
    #define id(x,y) (((x)-1)*n+(y))
    using namespace std;
    const int N=410;const double eps=1e-7;
    double a[N][N],p[N];
    inline void solve(int n){
    	for(int l=1;l<=n;l++){
    		int maxid=l;
    		for(int i=l+1;i<=n;i++)
    			if(fabs(a[i][l])>fabs(a[maxid][l]))maxid=i;
    		if(maxid!=l)swap(a[l],a[maxid]);
    		for(int i=l+1;i<=n;i++){
    			double t=a[i][l]/a[l][l];
    			for(int j=l;j<=n+1;j++)
    				a[i][j]-=t*a[l][j];
    		}
    	}
    	for(int i=n;i>=1;i--){
    		for(int j=i+1;j<=n;j++)a[i][n+1]-=a[j][n+1]*a[i][j];
    		a[i][n+1]/=a[i][i];
    	}
    }
    int n,head[N],nxt[N<<1],to[N<<1],num=0,m,S,T,in[N];
    inline void link(int x,int y){nxt[++num]=head[x];to[num]=y;head[x]=num;}
    int main(){
      freopen("pp.in","r",stdin);
      freopen("pp.out","w",stdout);
      int x,y;
      scanf("%d%d%d%d",&n,&m,&S,&T);
      for(int i=1;i<=m;i++){
    	  scanf("%d%d",&x,&y);
    	  link(x,y);link(y,x);
    	  in[x]++;in[y]++;
      }
      for(int i=1;i<=n;i++)cin>>p[i];
      for(int i=1;i<=n*n;i++)a[i][i]=1.0;
      a[id(S,T)][n*n+1]=1.0;
      for(int i=1;i<=n;i++){
    	  for(int j=1;j<=n;j++){
    		  if(i==j)continue;
    		  for(int k=head[j];k;k=nxt[k])
    			  a[id(i,to[k])][id(i,j)]-=p[i]*(1.0-p[j])/in[j];
    		  for(int k=head[i];k;k=nxt[k])
    			  a[id(to[k],j)][id(i,j)]-=p[j]*(1.0-p[i])/in[i];
    		  for(int k=head[i];k;k=nxt[k])
    			  for(int l=head[j];l;l=nxt[l])
    				  a[id(to[k],to[l])][id(i,j)]-=(1.0-p[i])*(1.0-p[j])/(in[i]*in[j]);
    		  a[id(i,j)][id(i,j)]-=p[i]*p[j];
    	  }
      }
      solve(n*n);
      for(int i=1;i<n;i++)printf("%.6lf ",a[id(i,i)][n*n+1]);
      printf("%.6lf",a[id(n,n)][n*n+1]);
      return 0;
    }
    
    
  • 相关阅读:
    使用浏览器的 Local Storage 真的安全吗?
    传统到敏捷的转型中,谁更适合做Scrum Master?
    HBM2E Flashbolt--提升人工智能的算力
    C语言 for 循环
    C语言自加自减运算符(++i / i++)
    C语言逗号表达式
    C语言逻辑运算符
    C语言三目运算符
    C语言条件判断 if / else
    C语言 printf 函数
  • 原文地址:https://www.cnblogs.com/Yuzao/p/8479691.html
Copyright © 2011-2022 走看看