题解 CF24D 【Broken robot】
Heartlessly · · 题解
Description
现在有一个机器人,最初站在
Source
[Luogu]CF24D
[Codeforces]24D
Solution
求期望步数,很容易想到 期望DP 。我们用
值得注意的是:
这个转移方程是倒推的,并且有后效性,所以不能直接转移。在求
同理,
我们会发现一共有
比如说,当
本来 高斯消元 的时间复杂度应该是
Code
#include <bits/stdc++.h>
using namespace std;
template <class T>
inline void read(T &x) {
x = 0;
char c = getchar();
bool f = 0;
for (; !isdigit(c); c = getchar()) f ^= c == '-';
for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
x = f ? -x : x;
}
const int MAXN = 1000;
int n, m, x, y;
double a[MAXN + 5][MAXN + 5], f[MAXN + 5][MAXN + 5];
inline void Gauss() {
for (int i = 1; i < m; ++i) {
double t = a[i][i];
a[i][i] = 1;
a[i][i + 1] /= t;
a[i][m + 1] /= t;
t = a[i + 1][i];
a[i + 1][i] = 0;
a[i + 1][i + 1] -= t * a[i][i + 1];
a[i + 1][m + 1] -= t * a[i][m + 1];
}//消元,消去下一行方程开头的未知数
a[m][m + 1] /= a[m][m];
a[m][m] = 1;//求出最后一个未知数的解
for (int i = m - 1; i; --i)
a[i][m + 1] -= a[i + 1][m + 1] * a[i][i + 1];//回带,消去下一行方程末尾的未知数
}
int main() {
freopen("eat.in", "r", stdin);
freopen("eat.out", "w", stdout);
read(n), read(m), read(x), read(y);
for (int i = n - 1; i >= x; --i) {
if (m == 1) {
a[1][1] = -1.0 / 2;
a[1][m + 1] = -f[i + 1][1] / 2.0 - 1;//特判 m = 1
} else {
a[1][1] = -2.0 / 3;
a[1][2] = 1.0 / 3;
a[1][m + 1] = -f[i + 1][1] / 3.0 - 1.0;
for (int j = 2; j < m; ++j) {
a[j][j] = -3.0 / 4;
a[j][j - 1] = a[j][j + 1] = 1.0 / 4;
a[j][m + 1] = -f[i + 1][j] / 4.0 - 1;
}
a[m][m] = -2.0 / 3;
a[m][m - 1] = 1.0 / 3;
a[m][m + 1] = -f[i + 1][m] / 3.0 - 1;
}//构造矩阵
Gauss();//高斯消元
for (int j = 1; j <= m; ++j) f[i][j] = a[j][m + 1];//赋值求出的解
}
printf("%.10lf\n", f[x][y]);
return 0;
}