一.题目链接:
CodeForces-24D
二.题目大意:
有一个 n × m 大小的地图,初始位置在 (x, y) 点.
每秒可向左、右、下走或不动,求从初始点到最后一行所需时间的期望.
三.分析:
设 dp[i][j] 为从 (i, j) 点走到最后一行时间的期望.
易得当 m == 1 时,此时只能向下走或不动,因此答案为 2 * (n - x).
当 m > 1 时:
经移项化简可得:
即:
设第一行
则
等式两边同除以 得:
令
则
同理可得:
其中
令
可得:
由最后两个式子可得:
之后递推回带可得所有 dp[i][j] 的值
四.代码实现:
#include <bits/stdc++.h>
using namespace std;
const int M = (int)1e3;
int n, m, x, y;
double a[M + 5], b[M + 5];
double dp[M + 5][M + 5];
void work()
{
for(int i = 1; i <= n; ++i)
dp[1][i] = 0;
for(int i = n - 1; i >= x; --i)
{
a[1] = -1.0 / 2.0;
b[1] = 1.0 / 2.0 * dp[i + 1][1] + 3.0 / 2.0;
for(int j = 2; j <= m - 1; ++j)
{
a[j] = (-1.0 / 4.0) / (1.0 / 4.0 * a[j - 1] + 3.0 / 4.0);
b[j] = (1.0 / 4.0 * b[j - 1] + 1.0 / 4.0 * dp[i + 1][j] + 1.0) / (1.0 / 4.0 * a[j - 1] + 3.0 / 4.0);
}
a[m] = -2.0;
b[m] = -3.0 - dp[i + 1][m];
dp[i][m] = (b[m] - b[m - 1]) / (a[m] - a[m - 1]);
for(int j = m - 1; j >= 1; --j)
dp[i][j] = b[j] - a[j] * dp[i][j + 1];
}
printf("%.4f\n", dp[x][y]);
}
int main()
{
scanf("%d %d %d %d", &n, &m, &x, &y);
if(m == 1)
printf("%d\n", 2 * (n - x));
else
work();
return 0;
}