Topcoder TorusSailing
TorusSailing
\(n \times m\) 的⽹格图,\((x,y)\)等概率⾛向 \(((x+1)\bmod n,y), (x,(y+1)\bmod m)\),问从 \((0,0)\)到某点的期望步数。
\(n,m≤100\)。
题解
经典的主元法例题。
由于点是往右下角走的,只需要对最后一行或最后一列的元素(除去右下角的那一个)建未知变量。其他的都可以用这些变量和一个常数线性表示成一个求和式。
通过变量的转移得到方程,就可以解出变量的值。最后代入左上角的求和式即可得到答案。
时间复杂度 \(O(n^3)\)。
代码
Topcoder要求传回一个double
,而我传回去一个long double
似乎也没事?
CO int N=100+10;
int idx[N][N],tot;
LD c[N][N][2*N];
LD a[2*N][2*N];
class TorusSailing{
public:
LD expectedTime(int n,int m,int X,int Y){
++X,++Y;
for(int i=1;i<n;++i){
if(i==X and m==Y) continue;
idx[i][m]=++tot,c[i][m][tot]=1;
}
for(int i=1;i<m;++i){
if(n==X and i==Y) continue;
idx[n][i]=++tot,c[n][i][tot]=1;
}
for(int i=n-1;i>=1;--i)for(int j=m-1;j>=1;--j){
if(i==X and j==Y) continue;
c[i][j][tot+1]=1;
for(int k=1;k<=tot+1;++k) c[i][j][k]+=0.5*(c[i+1][j][k]+c[i][j+1][k]);
}
if(n!=X or m!=Y){
c[n][m][tot+1]=1;
for(int i=1;i<=tot+1;++i) c[n][m][i]+=0.5*(c[1][m][i]+c[n][1][i]);
}
for(int i=1;i<n;++i){
int now=idx[i][m];
if(!now) continue;
a[now][now]=1,a[now][tot+1]=1;
for(int j=1;j<=tot;++j) a[now][j]-=0.5*(c[i+1][m][j]+c[i][1][j]);
a[now][tot+1]+=0.5*(c[i+1][m][tot+1]+c[i][1][tot+1]);
}
for(int i=1;i<m;++i){
int now=idx[n][i];
if(!now) continue;
a[now][now]=1,a[now][tot+1]=1;
for(int j=1;j<=tot;++j) a[now][j]-=0.5*(c[1][i][j]+c[n][i+1][j]);
a[now][tot+1]+=0.5*(c[1][i][tot+1]+c[n][i+1][tot+1]);
}
for(int i=1;i<=tot;++i){
int p=i;
for(int j=i+1;j<=tot;++j)
if(abs(a[j][i])>abs(a[p][i])) p=j;
if(p!=i) swap(a[p],a[i]);
for(int j=1;j<=tot;++j)if(j!=i){
LD coef=-a[j][i]/a[i][i];
for(int k=i;k<=tot+1;++k) a[j][k]+=coef*a[i][k];
}
}
for(int i=1;i<=tot;++i) a[i][tot+1]/=a[i][i],a[i][i]=1;
LD ans=0;
for(int i=1;i<=tot;++i) ans+=c[1][1][i]*a[i][tot+1];
ans+=c[1][1][tot+1];
return ans;
}
}tmp;
// int main(){
// int n=read<int>(),m=read<int>(),X=read<int>(),Y=read<int>();
// cout<<tmp.expectedTime(n,m,X,Y)<<endl;
// return 0;
// }
暴力
http://rsujskf.s602.xrea.com/?topcoder_srm614_div1_3
日本的科技是要先进一点。
// #includeなどは略しています
#define REP(i,a,b) for(i=a;i<b;i++)
#define rep(i,n) REP(i,0,n)
#define ll long long
class TorusSailing {
public:
double expectedTime(int N, int M, int X, int Y) {
int i, j, k, loop;
static double dp[101][101];
double res;
rep(i,N) rep(j,M) dp[i][j] = N*M;
dp[X][Y] = 0;
rep(loop,12000){
for(i=N-1;i>=0;i--) for(j=M-1;j>=0;j--){
if(i==X && j==Y) continue;
dp[i][j] = (dp[(i+1)%N][j] + dp[i][(j+1)%M]) * 0.5 + 1.0;
}
}
res = dp[0][0];
return res;
}
}
静渊以有谋,疏通而知事。