码迷,mamicode.com
首页 > 其他好文 > 详细

【BZOJ】1778: [Usaco2010 Hol]Dotp 驱逐猪猡

时间:2017-09-30 11:33:21      阅读:139      评论:0      收藏:0      [点我收藏+]

标签:pre   usaco   can   algo   print   str   for   oid   ret   

【题意】给定无向图,炸弹开始在1,在每个点爆炸概率p/q,不爆炸则等概率往邻点走,求在每个点爆炸的概率。

【算法】数学概率期望+高斯消元

【题解】令f[i]表示炸弹到达i点的概率(之前不爆炸)。

f[i]=∑f[j]*(1-Q)/d[j]

特别的,f[1]=∑f[j]*(1-Q)/d[j]+1(一开始就到达)。

只要一个点到就是到达,故使用概率加法。

使用高斯消元求解方程组,最后ansi=f[i]*Q

另一种思路,由于炸弹最终爆炸概率为1,所以sum=∑f[i],ansi=f[i]/sum

此题还有另一种解法,计算每个点到达次数的期望,到达概率和到达次数正相关(注意方程步数+1)。

技术分享
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=310,maxm=50010;
struct edge{int v,from;}e[maxm*2];
int first[maxn],tot,d[maxn],n,m,p,q;
double f[maxn][maxn];

void insert(int u,int v){tot++;e[tot].v=v;e[tot].from=first[u];first[u]=tot;d[v]++;}
void gauss(){
    for(int i=1;i<=n;i++){
        int t=i;
        for(int j=i+1;j<=n;j++)if(f[j][i]>f[t][i])t=j;
        if(t!=i)for(int j=i+1;j<=n;j++)swap(f[i][j],f[t][j]);
        for(int j=i+1;j<=n;j++)
            for(int k=n+1;k>=i;k--)
                f[j][k]-=f[j][i]/f[i][i]*f[i][k];
    }
    for(int i=n;i>=1;i--){
        for(int j=i+1;j<=n;j++)f[i][n+1]-=f[i][j]*f[j][n+1];
        f[i][n+1]/=f[i][i];
    }
}
int main(){
    scanf("%d%d%d%d",&n,&m,&p,&q);double Q=1.0*p/q;
    int u,v;
    for(int i=1;i<=m;i++){
        scanf("%d%d",&u,&v);
        insert(u,v);insert(v,u);
    }
    f[1][n+1]=1;
    for(int k=1;k<=n;k++){
        f[k][k]=1;
        for(int i=first[k];i;i=e[i].from)f[k][e[i].v]=-(1-Q)/d[e[i].v];
    }
    gauss();
    for(int i=1;i<=n;i++)printf("%.9lf\n",f[i][n+1]*Q);
    return 0;
}
View Code

 

【BZOJ】1778: [Usaco2010 Hol]Dotp 驱逐猪猡

标签:pre   usaco   can   algo   print   str   for   oid   ret   

原文地址:http://www.cnblogs.com/onioncyc/p/7613829.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!