【xsy1201】 随机游走 高斯消元
题目大意:你有一个n∗m的网格(有边界),你从(1,1)开始随机游走,求走到(n,m)的期望步数。
数据范围:n≤10,m≤1000。
我们令 f[i][j]表示从(1,1)随机游走到(i,j)的期望步数。不难推出:
如果(i,j)与边界不想邻,则有 $f[i][j]=\frac{1}{4}(f[i-1][j]+f[i+1][j]+f[i][j-1]+f[i][j+1])+1$
如果(i,j)与边界相邻,但不在四个角,则把式子中的14改为13,并且将括号中的四个项删掉一个。
如果(i,j)在非起点的三个角上,则式子也显然。
显然这是一个nm元一次方程,我们可以考虑用高斯消元在O(n3m3)的时间内完成求解,这样子可以拿到50分的好成绩。
我们令x(i−1)m+j来表示f[i][j]。
那么式子就变成了xi=14(xi−1+xi+1+xi+m+xi−m)+1
然后我们会发现,第i条式子只有[i−m,i+m]是有值的。
根据高斯消元的特征,第i条式子中包含x[i−m,i)的项值会被消掉,那么实际上存在项的部分为x[m,i+m]。
我们又发现,式子中包含xi的,只可能第i−m条式子至第i+m条式子。
那么,我们在高斯消元时,并不需要把对所有式子进行处理,只需要处理第i条式子的后m条式子的第i项至第i+m项即可。
时间复杂度降低至O(nm3),你可以得到80分的好成绩。
考虑到m很大,依然无法求解,考虑到n很小,我们将n和m进行swap,然后再去求解即可。
时间复杂度降低至O(n3m)。可以得到100分的好成绩。
1 #include<bits/stdc++.h> 2 #define M 10005 3 #define ok(x,y) (1<=(x)&&(x)<=n&&1<=(y)&&(y)<=m) 4 #define ok2(x,y) (ok(x,y)&&(!(x==1&&y==1))) 5 #define D double 6 using namespace std; 7 8 D *a[M];int n,m; 9 10 D get(int i,int j){ 11 D hh=0; 12 if(ok(i-1,j)) hh++; 13 if(ok(i+1,j)) hh++; 14 if(ok(i,j+1)) hh++; 15 if(ok(i,j-1)) hh++; 16 return 1/hh; 17 } 18 19 void newhh(int x){ 20 int i=(x-1)/m+1,j=(x-1)%m+1; 21 a[x]=new D[n*m+2]; 22 memset(a[x],0,sizeof(D)*(n*m+2)); 23 D hh=get(i,j); 24 if(ok2(i-1,j)) a[x][x-m]=-hh; 25 if(ok2(i+1,j)) a[x][x+m]=-hh; 26 if(ok2(i,j+1)) a[x][x+1]=-hh; 27 if(ok2(i,j-1)) a[x][x-1]=-hh; 28 a[x][x]=1; a[x][n*m+1]=1; 29 } 30 31 int Main(){ 32 scanf("%d%d",&n,&m); 33 if(n==1&&m==1) {printf("0\n"); return 0;} 34 if(m>n) swap(n,m); 35 for(int i=2;i<=m+2;i++) newhh(i); 36 for(int i=2;i<n*m;i++){ 37 for(int j=i+1;j<=min(i+m,n*m);j++){ 38 D hh=a[j][i]/a[i][i]; 39 for(int k=i;k<=min(i+m,n*m);k++) 40 a[j][k]-=hh*a[i][k]; 41 a[j][n*m+1]-=hh*a[i][n*m+1]; 42 } 43 delete[] a[i]; 44 if(i+m+1<=n*m) newhh(i+m+1); 45 } 46 D ans=a[n*m][n*m+1]/a[n*m][n*m]; 47 delete[] a[n*m]; 48 printf("%.0lf\n",ans); 49 } 50 51 int main(){ 52 int cas; cin>>cas; 53 while(cas--) Main(); 54 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!