R×C 迷宮,每格有傳送門:以概率 p0 留在原地,p1 向右,p2 向下。每次傳送消耗 2 魔法。從 (1,1) 到 (R,C) 的期望魔法消耗。R,C ≤ 1000。
設 `dp[i][j]` 為從 (i,j) 到終點的期望魔法值。終點 `dp[R][C] = 0`。
轉移方程:
`dp[i][j] = p0 * dp[i][j] + p1 * dp[i][j+1] + p2 * dp[i+1][j] + 2`
移項得:
`dp[i][j] = (p1 * dp[i][j+1] + p2 * dp[i+1][j] + 2) / (1 - p0)`
特殊情況:若 `p0 == 1` (死循環),`dp[i][j] = 0` (或視為不可達,但題目保證有解)。
依賴右方和下方狀態,按 行從下到上,列從右到左 逆序計算。
#include
#include
const int MAX = 1005;
const double EPS = 1e-10;
double p[3][MAX][MAX];
double dp[MAX][MAX];
int main() {
int R, C;
while (scanf("%d%d", &R, &C) == 2) {
for (int i = 1; i <= R; i++)
for (int j = 1; j <= C; j++)
scanf("%lf%lf%lf", &p[0][i][j], &p[1][i][j], &p[2][i][j]);
dp[R][C] = 0;
for (int i = R; i >= 1; i--) {
for (int j = C; j >= 1; j--) {
if (i == R && j == C) continue;
if (fabs(p[0][i][j] - 1.0) < EPS) {
dp[i][j] = 0; // 死循環,期望無限大但題目約束下不會作為答案
} else {
dp[i][j] = (p[1][i][j] * dp[i][j+1] + p[2][i][j] * dp[i+1][j] + 2) / (1.0 - p[0][i][j]);
}
}
}
printf("%.3f\n", dp[1][1]);
}
return 0;
}