題目
在一個n行m列的方陣中,一個機器人初始在(i,j),它隨機往(i,j+1),(i,j−1),(i+1,j)需要一個單位的時間,它也可以停留,問到達第n行的期望時間
分析
首先把初始座標以上的部分去掉
設f[i][j]表示從(i,j)出發到最後一行的期望時間
若m=1,f[i][1]=21(f[i][1]+f[i+1][1])+1
∴f[i][1]=f[i+1][1]+2
那麼f[i][j]=f[i+1][j]+2=⋯=2∗(n−1)
若m>1,f[i][j]=⎩⎪⎨⎪⎧31(f[i][j]+f[i][j+1]+f[i+1][j])+1(j=1)31(f[i][j]+f[i][j−1]+f[i+1][j])+1(j=m)41(f[i][j]+f[i][j−1]+f[i][j+1]+f[i+1][j])+1(1<j<m)
然而它是有後效性的,不可做,考慮高斯消元
於是得到三個方程
⎩⎪⎨⎪⎧2f[i][j]−f[i][j+1]−f[i+1][j]=3(j=1)2f[i][j]−f[i][j−1]−f[i+1][j]=3(j=m)3f[i][j]−f[i][j+1]−f[i][j−1]−f[i+1][j]=4(1<j<m)
但是這豈不是O(n6),考慮把下一行當做常量,那麼時間複雜度O(n4)
但是如果畫出這個矩陣,就可以知道這個矩陣比較稀疏,而且只需要維護T[i][i],T[i][i+1],T[i][m+1],時間複雜度優化到O(n2),實在是噁心至極
代碼
#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
double a[1011][1011],f[1011]; int n,m,x,y;
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void gauss(int n){
for (rr int i=1;i<=n;++i){
if (i<n) a[i][i+1]/=a[i][i];
a[i][n+1]/=a[i][i],a[i][i]=1;
a[i+1][i+1]-=a[i][i+1]*a[i+1][i];
a[i+1][n+1]-=a[i][n+1]*a[i+1][i]; a[i+1][i]=0;
}
for (rr int i=n-1;i;--i) a[i][n+1]-=a[i][i+1]*a[i+1][n+1];
}
signed main(){
n=iut(); m=iut(); n-=iut()-1,x=1,y=iut();
if (m==1) return !printf("%.10lf",(n-1)*2.0);
for (rr int j=1;j<n;++j){
a[1][1]=2,a[1][2]=-1,a[1][m+1]=f[1]+3;
a[m][m]=2,a[m][m-1]=-1,a[m][m+1]=f[m]+3;
for (rr int i=2;i<m;++i) a[i][i-1]=a[i][i+1]=-1;
for (rr int i=2;i<m;++i) a[i][i]=3,a[i][m+1]=f[i]+4;
gauss(m); for (rr int i=1;i<=m;++i) f[i]=a[i][m+1];
}
return !printf("%.10lf",f[y]);
}