[HDU 4418] Time travel
题目:给出一个长度为n的数轴和一个初始方向,一个人一次可以走[1,m]步,走到头就会自动反弹回来,求给定起点X到Y的期望步数
E[x]表示x点到终点的期望,则E[x]=sigma(E[x+i]+i),E[Y]=0
因为还有方向问题,所以我们把n个点拆成2*n-2个,原数轴01234变成01234321
即一个点表示沿固定方向到Y的期望
然后高斯消元解方程
n=1时需要特判
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define eps 1e-12// 4 #define maxn 205 5 int T,N,M,X,Y,D,F,A[maxn],vis[maxn],q[maxn]; 6 double ans[maxn],fnc[maxn][maxn],p[maxn]; 7 bool eq(double x,double y){ return fabs(x-y)<eps; } 8 bool judge(int s){ 9 int head=0,tail=0; 10 F=0,memset(vis,-1,sizeof(vis)); 11 vis[q[++tail]=s]=F++; 12 while(head<tail){ 13 int u=q[++head]; 14 for(int i=1;i<=M;i++){ 15 if(eq(p[i],0))continue; 16 int v=(u+i)%(2*N-2);//go die 17 if(vis[v]==-1)vis[q[++tail]=v]=F++; 18 } 19 } 20 return vis[Y]!=-1||vis[2*N-2-Y]!=-1; 21 } 22 void build(){ 23 memset(fnc,0,sizeof(fnc)); 24 for(int i=0;i<2*N-2;i++){ 25 if(vis[i]==-1)continue; 26 fnc[vis[i]][vis[i]]=1; 27 if(A[i]==Y)continue; 28 int u=vis[i]; 29 for(int j=1;j<=M;j++){ 30 int v=vis[(i+j)%(2*N-2)]; 31 if(v==-1)continue; 32 fnc[u][v]-=p[j]; 33 fnc[u][F]+=j*p[j]; 34 } 35 } 36 } 37 bool guass(){ 38 build(); 39 int cur=0,nxt; 40 for(int i=0;i<F;i++){ 41 for(nxt=cur;nxt<F;nxt++) 42 if(!eq(fnc[nxt][i],0))break; 43 if(nxt==F)continue; 44 if(nxt!=cur){ 45 for(int j=0;j<=F;j++) 46 swap(fnc[cur][j],fnc[nxt][j]); 47 } 48 for(int j=cur+1;j<F;j++) 49 if(!eq(fnc[j][i],0)){ 50 double val=fnc[j][i]/fnc[cur][i]; 51 for(int k=i;k<=F;k++) 52 fnc[j][k]-=val*fnc[cur][k]; 53 } 54 cur++; 55 } 56 for(int i=cur;i<F;i++) 57 if(!eq(fnc[i][F],0))return false; 58 for(int i=0;i<2*N-2;i++)ans[i]=-1; 59 for(int i=cur-1;i>=0;i--){ 60 double res=fnc[i][F]; 61 for(int j=F-1;j>=i;j--) 62 if(!eq(fnc[i][j],0)){// 63 if(eq(ans[j],-1))ans[j]=res/fnc[i][j]; 64 res-=ans[j]*fnc[i][j]; 65 } 66 } 67 return true; 68 } 69 int main(){ 70 scanf("%d",&T); 71 while(T--){ 72 scanf("%d%d%d%d%d",&N,&M,&Y,&X,&D); 73 for(int i=1;i<=M;i++) 74 scanf("%lf",&p[i]),p[i]/=100; 75 if(N==1)printf("%.2lf\n",0.0); 76 else{ 77 int s; 78 if(D==1)s=2*N-2-X; 79 else s=X; 80 for(int i=0;i<N;i++)A[i]=i; 81 for(int i=1;i<N-1;i++)A[2*N-2-i]=A[i]; 82 if(!judge(s))puts("Impossible !");// 83 else if(!guass())puts("Impossible !"); 84 else printf("%.2lf\n",ans[vis[s]]); 85 } 86 } 87 return 0; 88 }