题解CF#24 D-Broken Robots
Posted twilight-sx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解CF#24 D-Broken Robots相关的知识,希望对你有一定的参考价值。
在某次考试的时候用过的办法,懒人必备……【笑哭】
一个非常显然的 dp,我们用 (f[i][j]) 表示第 (i) 行第 (j) 列的格子走到最后一排的期望步数转移即为
(f[i][j] = frac{f[i][j - 1] + f[i][j + 1] + f[i + 1][j] + f[i][j]}{4} + 1)
略微的化一下简:
(f[i][j] = frac{f[i][j - 1] + f[i][j + 1] + f[i + 1][j] + 4}{3})
(当然,对于 j = 1 和 j = m 的情况是另外两个式子,但推导的方法是一样的)。这个式子使用高斯消元优化一下就能搞定,然而非常悲伤,像我这样的蒟蒻写高斯消元常常写挂,也不是很敢码。那怎么办办呢?人工大法好啊!
我们可以注意到行与行之间是不会相互转移的,我们可以认为当前行的 dp 数组为 f,下一行的 dp 数组为 g。那么对于 (f[i][m]) 而言,我们有
(f[m] = frac{f[m - 1] + g[m] + 3}{2})
也就是说,我们可以用 (f[i - 1]) 来表示出 (f[i]) 的值!
那么每从 (f[j] -> f[j - 1]),我们都可以得到一个递推式
(f]j] = k * f[j - 1] + t)
那么这个式子递归到尽头 f[1] 的时候
我们陡然发现式子中的未知数只剩下了一个 f[1]!
此时,只需不断回代就能得到 f[2 ... m]。
复杂度 (O(n * m)) ,非常优秀是吧~
#include <bits/stdc++.h> using namespace std; #define maxn 1050 #define db double int n, m, S, T; db f[maxn][maxn]; int read() { int x = 0, k = 1; char c; c = getchar(); while(c < ‘0‘ || c > ‘9‘) { if(c == ‘-‘) k = -1; c = getchar(); } while(c >= ‘0‘ && c <= ‘9‘) x = x * 10 + c - ‘0‘, c = getchar(); return x * k; } void DP(int p, int x, db k, db t) { if(!x) return; if(x == 1) { f[p][x] = (f[p + 1][x] + 3.0 + t) / (2.0 - k); return; } db k1 = 1 / (3.0 - k), t1 = (f[p + 1][x] + 4.0 + t) / (3.0 - k); DP(p, x - 1, k1, t1); f[p][x] = f[p][x - 1] * k1 + t1; } int main() { n = read(), m = read(), S = read(), T = read(); for(int i = n - 1; i >= 1; i --) { db k = 0.5, t = 0.5 * (3.0 + f[i + 1][m]); DP(i, m - 1, k, t); if(m == 1) f[i][m] = f[i + 1][m] + 2.0; else f[i][m] = k * f[i][m - 1] + t; } printf("%.10lf ", f[S][T]); return 0; }
以上是关于题解CF#24 D-Broken Robots的主要内容,如果未能解决你的问题,请参考以下文章