hdu 4481 Time travel(高斯求期望)(转)
(转)http://blog.csdn.net/u013081425/article/details/39240021
http://acm.hdu.edu.cn/showproblem.php?pid=4418
读了一遍题后大体明白意思,但有些细节不太确定。就是当它处在i点处,它有1~m步可以走,但他走的方向不确定呢。后来想想这个方向是确定的,就是他走到i点的方向,它会继续朝着这个方向走,直到转向回头。
首先要解决的一个问题是处在i点处,它下一步该到哪个点。为了解决方向不确定的问题,将n个点转化为2*(n-1)个点。例如当n=4时由原来的0123变为012321,它对应的编号为012345,这样就不用管它哪个方向,统一处理了,当向前走k步时即(i+k)%n。
然后设出dp[i]表示在i点处时到达终点的期望步数,那么可列出转移方程dp[i] = ∑( pk * (dp[ (x+k)%n ] +k) )。但是有些点是永远无法到达的,因此先bfs出所有到达的点,然后列出方程组解方程。
有许多注意的点,判断p[i]是否为0等。
1 #include <stdio.h> 2 #include <iostream> 3 #include <map> 4 #include <set> 5 #include <list> 6 #include <stack> 7 #include <vector> 8 #include <math.h> 9 #include <string.h> 10 #include <queue> 11 #include <string> 12 #include <stdlib.h> 13 #include <algorithm> 14 //#define LL __int64 15 #define LL long long 16 #define eps 1e-9 17 #define PI acos(-1.0) 18 using namespace std; 19 const int INF = 0x3f3f3f3f; 20 const int maxn = 210; 21 22 double p[maxn]; 23 double a[maxn][maxn];//增广矩阵 24 double X[maxn];//解集 25 int num[maxn];//给每个能给到达的point离散化 26 int n,m,x,y,d; 27 int equ,var,cnt; 28 29 bool Gauss() 30 { 31 int row,col,max_r,i,j; 32 row = 0; 33 col = 0; 34 while(row < equ && col < var) 35 { 36 max_r = row; 37 for(i = row+1; i < equ; i++) 38 { 39 if(fabs(a[i][col]) > fabs(a[max_r][col])) 40 max_r = i; 41 } 42 if(max_r != row) 43 { 44 for(j = col; j <= var; j++) 45 swap(a[row][j], a[max_r][j]); 46 } 47 if(fabs(a[row][col]) < eps) 48 { 49 col++; 50 continue; 51 } 52 for(i = row+1; i < equ; i++) 53 { 54 if(fabs(a[i][col]) < eps) continue; 55 double t = a[i][col]/a[row][col]; 56 a[i][col] = 0.0; 57 for(j = col+1; j <= var; j++) 58 a[i][j] -= a[row][j]*t; 59 } 60 row++; 61 col++; 62 } 63 64 for(i = row; i < equ; i++) 65 if(fabs(a[i][var]) > eps) 66 return false; //无解 67 for(i = equ-1; i >= 0; i--) 68 { 69 if(fabs(a[i][i]) < eps) continue; 70 double t = a[i][var]; 71 for(j = i+1; j < var; j++) 72 t -= a[i][j]*X[j]; 73 X[i] = t/a[i][i]; 74 } 75 return true; 76 } 77 78 void bfs(int s) //bfs找出所有能够到达的点并离散化 79 { 80 queue <int> que; 81 que.push(s); 82 num[s] = cnt++; 83 while(!que.empty()) 84 { 85 int u = que.front(); 86 que.pop(); 87 for(int i = 1; i <= m; i++) 88 { 89 if(fabs(p[i]) < eps) 90 continue; 91 int v = (u+i)%n; 92 if(num[v] == -1) 93 { 94 num[v] = cnt++; 95 que.push(v); 96 } 97 } 98 } 99 } 100 101 int main() 102 { 103 int test; 104 scanf("%d",&test); 105 for(int item = 1; item <= test; item++) 106 { 107 scanf("%d %d %d %d %d",&n,&m,&y,&x,&d); 108 for(int i = 1; i <= m; i++) 109 { 110 scanf("%lf",&p[i]); 111 p[i] /= 100; 112 } 113 if(x == y) 114 { 115 printf("0.00\n"); 116 continue; 117 } 118 n = 2*(n-1); 119 if(d == 1) 120 x = n-x; 121 memset(num,-1,sizeof(num)); 122 cnt = 0; 123 bfs(x); 124 if(num[y] == -1 && num[n-y] == -1) //注意这里是 &&,只有当两个方向都走不到才算走不到 125 { 126 printf("Impossible !\n"); 127 continue; 128 } 129 130 memset(a,0,sizeof(a)); 131 memset(X,0,sizeof(X)); 132 equ = var = cnt; 133 134 for(int i = 0; i < n; i++) 135 { 136 if(num[i] != -1) 137 { 138 if(i == y || i == n-y) //注意特判终点 139 { 140 a[num[i]][num[i]] = 1; 141 a[num[i]][cnt] = 0; 142 continue; 143 } 144 a[num[i]][num[i]] = 1; 145 for(int j = 1; j <= m; j++) 146 { 147 int t = (i+j)%n; 148 if(num[t] != -1) 149 a[num[i]][num[t]] -= p[j]; 150 a[num[i]][cnt] += j*p[j]; 151 } 152 } 153 } 154 if(Gauss()) 155 printf("%.2lf\n",X[num[x]]); 156 else printf("Impossible !\n"); 157 } 158 return 0; 159 }