题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4418
题意:简单来说就是给你1个环(n - 1 , n - 2 …… 0 ,1 , 2 , 3 …… n - 2)。你可以走1 - m步每步的概率是给定的。。保证sum(pk)(1 <= k <= m)的和是100,问你从x开始给你一个初始方向走到y的期望步数是多少。d = 0 代表从0 ->n - 1 ,d = 1代表从n - 1 -> 0。
由于这里同一个点每次转移的方向是不一样的,因此要进行拆点,即0, 1, 2, 3 -> 0, 1, 2, 3, 4, 5,4和5分别表示2和1这个点的相反的方向。然后做一遍BFS,看是否能到达Y点,如果能的话,列出期望方程:E[i]=Σ( (E[j]+k)*p[k] ),然后高斯消元,这里高斯方程可以把不能到达的点都去掉,也可以把它的期望设为OO(无穷大),因为这里精度只有0.01...
1 //STATUS:C++_AC_312MS_800KB 2 #include <functional> 3 #include <algorithm> 4 #include <iostream> 5 //#include <ext/rope> 6 #include <fstream> 7 #include <sstream> 8 #include <iomanip> 9 #include <numeric> 10 #include <cstring> 11 #include <cassert> 12 #include <cstdio> 13 #include <string> 14 #include <vector> 15 #include <bitset> 16 #include <queue> 17 #include <stack> 18 #include <cmath> 19 #include <ctime> 20 #include <list> 21 #include <set> 22 #include <map> 23 using namespace std; 24 #pragma comment(linker,"/STACK:102400000,102400000") 25 //using namespace __gnu_cxx; 26 //define 27 #define pii pair<int,int> 28 #define mem(a,b) memset(a,b,sizeof(a)) 29 #define lson l,mid,rt<<1 30 #define rson mid+1,r,rt<<1|1 31 #define PI acos(-1.0) 32 //typedef 33 typedef __int64 LL; 34 typedef unsigned __int64 ULL; 35 //const 36 const int N=210; 37 const int INF=0x3f3f3f3f; 38 const LL MOD=1000000007,STA=8000010; 39 const LL LNF=1LL<<55; 40 const double EPS=1e-9; 41 const double OO=1e9; 42 const int dx[4]={-1,0,1,0}; 43 const int dy[4]={0,1,0,-1}; 44 const int day[13]={0,31,28,31,30,31,30,31,31,30,31,30,31}; 45 //Daily Use ... 46 inline int sign(double x){return (x>EPS)-(x<-EPS);} 47 template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;} 48 template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;} 49 template<class T> inline T lcm(T a,T b,T d){return a/d*b;} 50 template<class T> inline T Min(T a,T b){return a<b?a:b;} 51 template<class T> inline T Max(T a,T b){return a>b?a:b;} 52 template<class T> inline T Min(T a,T b,T c){return min(min(a, b),c);} 53 template<class T> inline T Max(T a,T b,T c){return max(max(a, b),c);} 54 template<class T> inline T Min(T a,T b,T c,T d){return min(min(a, b),min(c,d));} 55 template<class T> inline T Max(T a,T b,T c,T d){return max(max(a, b),max(c,d));} 56 //End 57 58 /* gauss_elimination O(n^3) 59 n个方程n个变元 60 要求系数矩阵可逆 61 A[][]是增广矩阵,即A[i][n]是第i个方程右边的常数bi 62 运行结束后A[i][n]是第i个未知数的值 */ 63 int vis[N]; 64 double p[N]; 65 int T,n,m,Y,X,D,up; 66 67 double A[N][N]; 68 69 void gauss(int n) 70 { 71 int i,j,k,r; 72 for(i=0;i<n;i++){ 73 //选一行与r与第i行交换,提高数据值的稳定性 74 r=i; 75 for(j=i+1;j<n;j++) 76 if(fabs(A[j][i]) > fabs(A[r][i]))r=j; 77 if(r!=i)for(j=0;j<=n;j++)swap(A[r][j],A[i][j]); 78 //i行与i+1~n行消元 79 /* for(k=i+1;k<n;k++){ //从小到大消元,中间变量f会有损失 80 double f=A[k][i]/A[i][i]; 81 for(j=i;j<=n;j++)A[k][j]-=f*A[i][j]; 82 }*/ 83 for(j=n;j>=i;j--){ //从大到小消元,精度更高 84 for(k=i+1;k<n;k++) 85 A[k][j]-=A[k][i]/A[i][i]*A[i][j]; 86 } 87 } 88 //回代过程 89 for(i=n-1;i>=0;i--){ 90 for(j=i+1;j<n;j++) 91 A[i][n]-=A[j][n]*A[i][j]; 92 A[i][n]/=A[i][i]; 93 } 94 } 95 96 int bfs() 97 { 98 int i,u,v; 99 queue<int> q; 100 mem(vis,0); 101 q.push(X); 102 vis[X]=1; 103 while(!q.empty()) 104 { 105 u=q.front();q.pop(); 106 if(u==Y || u==up-Y)A[u][up]=0; 107 A[u][u]=1; 108 for(i=1;i<=m;i++){ 109 v=((u+i*D)%up+up)%up; 110 if(u!=Y && u!=up-Y)A[u][v]-=p[i]; 111 if(sign(p[i]) && !vis[v]){ 112 vis[v]=1; 113 q.push(v); 114 } 115 } 116 } 117 for(i=0;i<up;i++){ 118 if(!vis[i])A[i][i]=1,A[i][up]=OO; 119 } 120 return vis[Y] || vis[up-Y]; 121 } 122 123 int main(){ 124 // freopen("in.txt","r",stdin); 125 int i,j; 126 double t; 127 scanf("%d",&T); 128 while(T--) 129 { 130 scanf("%d%d%d%d%d",&n,&m,&Y,&X,&D); 131 if(!X || !D)D=1; 132 else D=-1; 133 t=0; 134 for(i=1;i<=m;i++){ 135 scanf("%lf",&p[i]); 136 p[i]/=100; 137 t+=i*p[i]; 138 } 139 if(X==Y){ 140 printf("0.00\n"); 141 continue; 142 } 143 up=n+n-2; 144 mem(A,0); 145 for(i=0;i<up;i++)A[i][up]=t; 146 if(bfs()){ 147 gauss(up); 148 printf("%.2lf\n",A[X][up]); 149 } 150 else printf("Impossible !\n"); 151 } 152 return 0; 153 }