题目大意:
一个人在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 }