1. 程式人生 > >jzoj3657 [NOI2014模擬]隨機遊走

jzoj3657 [NOI2014模擬]隨機遊走

Description

在一個二維平面上每次隨意往四周一個方向上行走的模型叫隨機遊走。現在對這個模型進行一些修改:有一個n*m的矩陣,你初始站在(1,1),想要走到(n,m),每次隨機往四周不超出矩形方向走一步,問走到(n,m)的期望步數。

這裡寫圖片描述

Solution

第一眼裸題,學乖了看看資料範圍發現反而不太會了
可以設第一行或第一列全部為未知數,表示點到(n,m)的期望距離,那麼就能推出下一行/列,高斯消元即可。注意只有一行或只有一列的情況,略坑
這題顯然按列做比較優秀

Code

#include <stdio.h>
#include <string.h>
#include <algorithm> #include <math.h> #define rep(i,st,ed) for (int i=st;i<=ed;++i) #define drp(i,st,ed) for (int i=st;i>=ed;--i) #define fill(x,t) memset(x,t,sizeof(x)) #define copy(x,t) memcpy(x,t,sizeof(x)) const int N=205; double last[N][N],a[N][N]; void gauss(int n) { rep(i,1
,n-1) { rep(j,i+1,n) { if (fabs(a[j][i])>fabs(a[i][i])) std:: swap(a[i],a[j]); } rep(j,i+1,n) { double tmp=a[j][i]/a[i][i]; rep(k,i,n*2) a[j][k]-=a[i][k]*tmp; a[j][0]-=a[i][0]*tmp; } } drp(i,n-1,1) { rep(j,i+1
,n) { double tmp=a[i][j]/a[j][j]; a[i][j]=0; a[i][0]-=a[j][0]*tmp; rep(k,n+1,n*2) a[i][k]-=a[j][k]*tmp; } } } int main(void) { int T; scanf("%d",&T); while (T--) { int n,m; scanf("%d%d",&n,&m); fill(a,0); rep(i,1,n) { a[i][i]=1; a[i][0]=1; if (i!=n) { double tmp=1; if (m!=1) tmp++; if (i!=1) tmp++; a[i][i+1]=-1.0/tmp; if (m!=1) a[i][i+n]=-1.0/tmp; if (i!=1) a[i][i-1]=-1.0/tmp; } } gauss(n); rep(i,1,m-1) { copy(last,a); fill(a,0); rep(j,1,n) { a[j][j]=1; a[j][0]=1; double tmp=1; if (j!=n) tmp++; if (j!=1) tmp++; if (i!=m-1) tmp++; if (j!=n) a[j][j+1]=-1.0/tmp; if (j!=1) a[j][j-1]=-1.0/tmp; if (i!=m-1) a[j][j+n]=-1.0/tmp; tmp=-1.0/tmp/last[j][j]; rep(k,1,n) a[j][k]-=tmp*last[j][k+n]; a[j][0]-=tmp*last[j][0]; } gauss(n); } printf("%.0lf\n", (a[1][0]/a[1][1]-1)); } return 0; }