• bzoj 3270 博物馆


    题目大意

    给你一个图
    每个时刻一个人p[i]的概率不懂
    1-p[i]的概率动
    动的话等概率的走其中一条边
    求两个人一个一开始在S,另一个一开始在T,
    求对于每个点i,他们在i,i相遇的概率

    分析

    大致同bzoj 3143
    定义二元组((x,y))表示第一个人在x,第二个人在y的状态
    可以把这些二元组状态看成一些点
    对每个点定义(E[i])
    表示点i的期望经过次数
    考虑它可以从什么状态转移过来
    要么都不动,要么都动,要么一个动一个不动
    注意的是碰面后不能再分离然后又碰面这样
    所以对于二元组((i,i)),我们把它视为一个结束节点
    另外对于二元组((S,T)),我们把它视为一个起始节点
    还有要注意(E[起始点])的期望式为其它点转移到它的期望再(+1),因为每种走法都会经过起点一次
    为什么(E(结束点)=P(结束点))呢?
    因为是结束节点,到了它之后就不能再走了,经过次数只会为1
    根据期望表达式(E=sum_{step}step*P(step))
    该点概率就是(P(step=1)=E)

    solution

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    using namespace std;
    typedef long double db;
    const int M=407;
    
    inline int rd(){
    	int x=0;bool f=1;char c=getchar();
    	for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
    	for(;isdigit(c);c=getchar()) x=x*10+c-48;
    	return f?x:-x;
    }
    
    int n,m,nn;
    int S,T;
    int du[M];
    db p[M];
    
    int id(int x,int y){
    	return (x-1)*n+y;
    }
    
    struct Guass{
    	db a[M][M];
    	db res[M];
    	int n,m;
    	void init(int sz){
    		n=sz;
    		m=sz+1;
    		memset(a,0,sizeof(a));
    		memset(res,0,sizeof(res));
    	}
    	void xiao(int x,db ff,int y){
    		for(int i=1;i<=m;i++) a[y][i]-=a[x][i]*ff;
    	}
    	void getres(){
    		int i,j;
    		db tp;
    		res[m]=1;
    		for(i=n;i>0;i--){
    			tp=0;
    			for(j=i+1;j<=m;j++) tp+=a[i][j]*res[j];
    			res[i]=(-tp)/a[i][i];
    		}
    		res[m]=0;
    	}
    	void gauss(){
    		int i,j;
    		for(i=1;i<m;i++){
    			for(j=i;j<=n;j++)
    			if(a[j][i]){
    				swap(a[j],a[i]);
    				break;
    			}
    			for(j=1;j<=n;j++)
    			if(a[j][i]&&j!=i) xiao(i,a[j][i]/a[i][i],j);
    		}
    		getres();
    	}
    }GS;
    
    vector<int>g[M];
    
    int main(){
    	n=rd(),m=rd();
    	S=rd(),T=rd();
    
    	int i,j,x,y,nw,to;
    
    	for(i=1;i<=m;i++){
    		x=rd(),y=rd();
    		du[x]++; du[y]++;
    		g[x].push_back(y);
    		g[y].push_back(x);
    	}
    
    	for(i=1;i<=n;i++) scanf("%Lf",p+i);
    
    	nn=n*n;
    	GS.init(nn);
    	for(i=1;i<=n;i++)
    	for(j=1;j<=n;j++){
    		nw=id(i,j);
    		for(x=1;x<=g[i].size();x++)
    		for(y=1;y<=g[j].size();y++){
    			to=id(g[i][x-1],g[j][y-1]);
    			GS.a[to][nw]+=(1-p[i])/du[i]*(1-p[j])/du[j];
    		}
    		for(x=1;x<=g[i].size();x++){
    			to=id(g[i][x-1],j);
    			GS.a[to][nw]+=(1-p[i])/du[i]*p[j];
    		}
    		for(y=1;y<=g[j].size();y++){
    			to=id(i,g[j][y-1]);
    			GS.a[to][nw]+=p[i]*(1-p[j])/du[j];
    		}
    		GS.a[nw][nw]+=p[i]*p[j];
    	}
    	nw=id(S,T);
    	GS.a[nw][nn+1]+=1.0;
    	for(i=1;i<=n;i++)
    	for(nw=1;nw<=nn;nw++)GS.a[nw][id(i,i)]=0;//碰面后就不能再找一次了
    	for(i=1;i<=nn;i++) GS.a[i][i]-=1.0;
    	
    	GS.gauss();
    	
    	for(i=1;i<=n;i++) printf("%Lf ",GS.res[id(i,i)]);
    
    	return 0;
    }
    
  • 相关阅读:
    IIS10保存配置文件及导入、导出、备份、还原
    centos7 根分区扩容
    mssqlserver2014安装步骤
    error:class 'socket.error' [Errno 2] No such file or directory: file: /usr/lib64/python2.7/socket.py line: 224
    Centos7安装Redis-5.0.3
    Aspose 学习笔记
    Maven学习笔记
    【web性能测试随笔】一、项目介绍及工具
    【Python学习笔记】python开发环境安装部署
    微信小程序中遮罩层滚动穿透问题(view增加一个属性解决)
  • 原文地址:https://www.cnblogs.com/acha/p/6421227.html
Copyright © 2020-2023  润新知