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
" , a[0][cnt]);
122 
123     }
124     return 0;
125 }
原文地址:https://www.cnblogs.com/CSU3901130321/p/4534686.html