HDU 4418 高斯消元解决概率期望

  题目大意:

一个人在n长的路径上走到底再往回,走i步停下来的概率为Pi , 求从起点开始到自己所希望的终点所走步数的数学期望

 

因为每个位置都跟后m个位置的数学期望有关

E[i] = sigma((E[i+j]+j)*P[j])

我们需要将模型转化一下,本来路径为012345这样,因为来回走,我们多定义n-2个点就是 0123454321然后利用取模就可以不断找到下一组相关的m个点

列出多元方程组,利用高斯消元解决问题

  1 #include <cstdio>

  2 #include <cstring>

  3 #include <iostream>

  4 #include <algorithm>

  5 #include <cmath>

  6 #include <queue>

  7 using namespace std;

  8 const int N = 205;

  9 #define eps 1e-8

 10 

 11 double a[N][N] , x[N] , p[N] , sum;

 12 int n,m,st,en,dire;

 13 int id[N] , cnt;//cnt记录需要求解的未知数个数

 14 

 15 queue<int> q;

 16 bool bfs()

 17 {

 18     memset(id , -1 , sizeof(id));

 19     cnt = 0;

 20     id[st] = cnt++;

 21     q.push(st);

 22     while(!q.empty())

 23     {

 24         int u=q.front();

 25         q.pop();

 26         for(int i=1 ; i<=m ; i++){

 27             int v = (u+i)%n;

 28             if(fabs(p[i])<eps || id[v]>=0) continue;

 29             id[v] = cnt++;

 30             q.push(v);

 31         }

 32     }

 33     return id[en]>=0 || id[n-en]>=0; //终点有两个

 34 }

 35 //建立多元方程组

 36 void build()

 37 {

 38     memset(a , 0 , sizeof(a));

 39     for(int i=0 ; i<n ; i++){

 40         if(id[i] < 0) continue;

 41         int u=id[i];

 42         a[u][u] = 1;

 43         if(u == id[en] || u == id[n-en]) {a[u][cnt]=0;continue;}

 44         for(int j=1 ; j<=m ; j++){

 45             int v =  (i+j)%n;

 46             if(id[v]<0) continue;

 47             v = id[v];

 48             a[u][v] -= p[j];

 49             a[u][cnt] += p[j]*j;

 50         }

 51     }

 52    /* for(int i=0 ; i<n ; i++)

 53         {

 54             for(int j=0 ; j<=n ; j++)

 55                 cout<<a[i][j]<<" ";

 56             cout<<endl;

 57         }*/

 58 }

 59 

 60 int gauss(int n)

 61 {

 62     int i,j,k;

 63     for(i=0,j=0 ; i<n&&j<n ; j++){

 64         for(k=i ; k<n ; k++)

 65             if(fabs(a[k][j])>=eps) break;

 66         if(k<n){

 67             if(i!=k){

 68                 for(int r=j ; r<=n ; r++)

 69                     swap(a[i][r],a[k][r]);

 70             }

 71             double tt=1.0/a[i][j];

 72             for(int r=j ; r<=n ; r++)

 73                 a[i][r]*=tt;

 74             for(int r=0 ; r<n ; r++) //这从 0~n ,整个2重循环相当于消去和回代同时操作

 75                 if(r!=i){

 76                     for(int t=n ; t>=j ; t--) //一定是递减序

 77                         a[r][t] -= a[r][j]*a[i][t];

 78                 }

 79             i++;

 80         }

 81     }

 82     //检查是否还有未满足的方程式

 83     for(int r=i ; r<n ; r++)

 84         if(fabs(a[r][n])>=eps)

 85             return 0;

 86     return 1;

 87 }

 88 

 89 int main()

 90 {

 91     #ifndef ONLINE_JUDGE

 92         freopen("a.in" , "r" , stdin);

 93     #endif // ONLINE_JUDGE

 94     int T;

 95     scanf("%d" , &T);

 96     while(T--)

 97     {

 98         scanf("%d%d%d%d%d" , &n , &m , &en , &st , &dire);

 99         n = 2*n-2;

100         sum = 0;

101         for(int i=1 ; i<=m ; i++){

102             int v;

103             scanf("%d" , &v);

104             p[i] = v*1.0/100.0;

105             sum += p[i]*i;

106         }

107         if(st == en){

108             puts("0.00");

109             continue;

110         }

111         if(dire>0) st = n-st;

112         if(!bfs()){

113             puts("Impossible !");

114             continue;

115         }

116         build();

117         if(!gauss(cnt)) {

118             puts("Impossible !");

119             continue;

120         }

121         printf("%.2f\n" , a[0][cnt]);

122 

123     }

124     return 0;

125 }

 

你可能感兴趣的:(HDU)