题目大意
给你一个n*m的平面,从(0,0)随机往上或右走。走到上边界时可以穿到最下边,到右边界时可以穿到最左边。问走到(x,y)的期望步数。
思路:
将左边界和下边界上的格子设为元,然后所有的格子的期望值都可以用这些元来表示。然后高斯消元解除元的值,回带到x,y就可以了
c o d e code code
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
const int MAXN = 510;
int n, m, S, T, tot;
double f[MAXN][MAXN][MAXN], g[MAXN][MAXN];
int b[MAXN][MAXN];
void add(int x, int y, int x1, int y1) {
for(int i = 0; i <= n + m - 2; i ++)
f[x][y][i] += (f[x][y1][i] + f[x1][y][i]) / 2.0;
}
void Gauss() {
int l;
double tmp;
for(int i = 0; i < tot; i ++) {
l = i;
for(int j = i + 1; j < tot; j ++)
if(fabs(g[l][i]) < fabs(g[j][i])) l = j;
if(i != l) for(int j = i; j <= tot; j ++) swap(g[l][j], g[i][j]);
tmp = g[i][i];
for(int j = i; j <= tot; j ++) g[i][j] /= tmp;
for(int j = 0; j < tot; j ++)
if(i != j) {
tmp = g[j][i];
for(int k = i; k <= tot; k ++) g[j][k] -= g[i][k] * tmp;
}
}
}
int main() {
// freopen("walk.in", "r", stdin);
// freopen("walk.out", "w", stdout);
scanf("%d%d%d%d", &n, &m, &S, &T);
for(int i = 1; i < n; i ++) f[i][0][tot] = 1.0, b[i][0] = tot, tot ++;
for(int i = 1; i < m; i ++) f[0][i][tot] = 1.0, b[0][i] = tot, tot ++;
for(int i = 1; i < n; i ++) {
for(int j = 1; j < m; j ++) {
int x = i - 1, y = j - 1;
add(i, j, x, y);
f[i][j][n + m - 2] += 1.0;
}
}
for(int i = 1; i < n; i ++) {
int x = b[i][0];
for(int k = 0; k <= n + m - 3; k ++) f[i][0][k] -= f[i][m - 1][k] / 2.0;
if(i != 1) f[i][0][b[i - 1][0]] -= 0.5;
f[i][0][n + m - 2] = f[i][0][n + m - 2] + f[i][m - 1][n + m - 2] / 2.0 + 1.0;
for(int k = 0; k <= n + m - 2; k ++) g[x][k] = f[i][0][k];
}
for(int j = 1; j < m; j ++) {
int x = b[0][j];
for(int k = 0; k <= n + m - 3; k ++) f[0][j][k] -= f[n - 1][j][k] / 2.0;
if(j != 1) f[0][j][b[0][j - 1]] -= 0.5;
f[0][j][n + m - 2] = f[0][j][n + m - 2] + f[n - 1][j][n + m - 2] / 2.0 + 1.0;
for(int k = 0; k <= n + m - 2; k ++) g[x][k] = f[0][j][k];
}
Gauss();
if(S == 0 || T == 0) {
printf("%.18lf", g[b[S][T]][n + m - 2]);
return 0;
}
double ans = 0;
for(int i = 0; i <= n + m - 3; i ++)
ans += f[S][T][i] * g[i][n + m - 2];
printf("%.18lf", ans + f[S][T][n + m - 2]);
return 0;
}