题解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的主要内容,如果未能解决你的问题,请参考以下文章

CF1335F Robots on a Grid

CF1045G AI robots(动态开点线段树)

题解LuoguP5894IOI2013robots

题解 CF1063B Labyrinth

CF Round #631 题解

CF886E 题解