【sdut2878】Circle
题目链接http://acm.sdut.edu.cn/onlinejudge2/index.php/Home/Index/problemdetail/pid/2878.html
题意
n个结点编号为0到n-1组成一个环。如果当前在结点x,那么它等概率的走向 (x+1)mod n,(x-1) 问从0到x的期望步数是多少
分析
高斯消元解决带环概率DP
f[i]表示当前在i结点,走到x结点得期望步数。f[x]=0。
f[i]=f[i+1]*0.5+f[i-1]*0.5+1
整理得到 1=f[i+1]*0.5+f[i-1]*0.5-f[i] 所以得到了n个方程组有n个未知量,然后通过高斯消元求解。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 #include <cmath> 6 7 using namespace std; 8 const int maxn=1000+100; 9 double f[maxn],a[maxn][maxn]; 10 int T,n,x; 11 void Gauss(){ 12 int k,col; 13 for(k=0,col=0;k<n&&col<n;k++,col++){ 14 int max_k=k; 15 for(int i=k;i<n;i++){ 16 if(fabs(a[i][col])>fabs(a[max_k][col]))max_k=i; 17 } 18 if(max_k!=k){ 19 for(int i=0;i<=n;i++) 20 swap(a[k][i],a[max_k][i]); 21 } 22 if(a[k][col]==0){ 23 k--; 24 continue; 25 } 26 for(int i=k+1;i<n;i++){ 27 if(a[i][col]){ 28 double g=a[i][col]/a[k][col]; 29 for(int j=0;j<=n;j++){ 30 a[i][j]-=a[k][j]*g; 31 } 32 } 33 } 34 } 35 for(int i=n-1;i>=0;i--){ 36 double g=a[i][n]; 37 for(int j=i+1;j<n;j++){ 38 if(a[i][j]!=0){ 39 g-=a[i][j]*f[j]; 40 } 41 } 42 f[i]=g/a[i][i]; 43 } 44 return ; 45 } 46 int main(){ 47 scanf("%d",&T); 48 for(int t=1;t<=T;t++){ 49 memset(a,0,sizeof(a)); 50 scanf("%d%d",&n,&x); 51 for(int i=0;i<n;i++){ 52 if(i==0){ 53 a[i][i]=1.0; 54 a[i][n]=0; 55 }else{ 56 a[i][i]=1.0; 57 a[i][(i+1)%n]=-0.5; 58 a[i][i-1]=-0.5; 59 a[i][n]=1; 60 } 61 } 62 Gauss(); 63 printf("%.4f\n",f[x]); 64 } 65 return 0; 66 }