zoukankan      html  css  js  c++  java
  • 洛谷2973 [USACO10HOL]赶小猪Driving Out the Piggi… 概率 高斯消元

    欢迎访问~原文出处——博客园-zhouzhendong

    去博客园看该题解


    题目传送门 - 洛谷2973


    题意概括

      N个城市,M条双向道路组成的地图,城市标号为1到N。“西瓜炸弹”放在1号城市,保证城市1至少连接着一个其他城市。“西瓜炸弹”有P/Q的概率会爆炸,每次进入其它城市时,爆炸的概率相同。如果它没有爆炸,它会随机的选择一条道路到另一个城市去,对于当前城市所连接的每一条道路都有相同的可能性被选中。对于给定的地图,求每个城市“西瓜炸弹”爆炸的概率。


    题解

      通过概率关系构建方程:

      其中in[j]表示节点j的出度,$F_i$ 表示最终在节点 $i$ 爆炸的概率。

    $$F_i = sum_{存在j到 i 的边}cfrac{(1-frac PQ)F_j}{in[j]}+cfrac PQ cdot [i=1]$$

      然后高斯消元跑一跑就可以了。


    代码

    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <cstdio>
    #include <cstdlib>
    using namespace std;
    const int N=300+5;
    const double Eps=1e-9;
    int n,m,P,Q,cnt[N];
    bool g[N][N];
    double p,a[N][N],x[N];
    void Gauss(){
    	int row=n,col=n,k,c;
    	for (k=c=1;k<=row,c<=col;k++,c++){
    		int Mk=k;
    		for (int i=k+1;i<=row;i++)
    			if (fabs(a[Mk][c])<fabs(a[i][c]))
    				Mk=i;
    		if (fabs(a[Mk][c])<Eps){
    			k--;
    			continue;
    		}
    		if (k!=Mk)
    			for (int i=c;i<=col+1;i++)
    				swap(a[k][i],a[Mk][i]);
    		for (int i=k+1;i<=row;i++)
    			for (int j=col+1;j>=c;j--)
    				a[i][j]=a[i][j]-a[k][j]*a[i][c]/a[k][c];
    	}
    	memset(x,0,sizeof x);
    	for (int i=k;i>=1;i--){
    		x[i]=a[i][n+1];
    		for (int j=i+1;j<=n;j++)
    			x[i]-=a[i][j]*x[j];
    		x[i]/=a[i][i];
    	}
    }
    int main(){
    	scanf("%d%d%d%d",&n,&m,&P,&Q);
    	p=double(P)/double(Q);
    	memset(g,0,sizeof g);
    	memset(cnt,0,sizeof cnt);
    	for (int i=1,a,b;i<=m;i++){
    		scanf("%d%d",&a,&b);
    		g[a][b]=g[b][a]=1;
    		cnt[a]++,cnt[b]++;
    	}
    	memset(a,0,sizeof a);
    	a[1][n+1]=p;
    	for (int i=1;i<=n;i++)
    		for (int j=1;j<=n;j++){
    			if (i==j){
    				a[i][j]=1;
    				continue;
    			}
    			if (!g[i][j])
    				continue;
    			double del=(1.0-p)/double(cnt[j]);
    			a[i][j]-=del;
    		}
    	Gauss();
    	for (int i=1;i<=n;i++)
    		if (fabs(x[i])<Eps)
    			x[i]=0;
    	for (int i=1;i<=n;i++)
    		printf("%.9lf
    ",x[i]);
    	return 0;
    }
    

    以前打错的公式就让他暂时存一下吧……

  • 相关阅读:
    14款响应式布局的前端开发框架
    如何在本地进行微信公众号的开发调试
    微信公众帐号应用开发—本地调试
    利用H5开发微信公众号
    微信公众平台开发入门教程
    JAVA编程不得不看的几本经典书籍
    使用百度UMeditor富文本编辑器,修改自定义图片上传,修改源码
    网站建设需要哪些程序
    Visual Studio 2013 中使用断点
    Objective-c 实例变量的访问级别
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/LuoguP2973.html
Copyright © 2011-2022 走看看