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;
}

}

posted on 2019-12-24 21:16  autoint  阅读(265)  评论(0编辑  收藏  举报

导航