CF 24 D. Broken robot

D. Broken robot

链接

题意:

  一个方格,从(x,y)出发,等价的概率向下,向左,向右,不动。如果在左右边缘上,那么等价的概率不动,向右/左,向下。走到最后一行即结束。求期望结束的步数。

分析:

  因为不能往上走,所以行与行之间存在转移,即上一行转移到下一行。

  同一行内的位置可以互相转移,所以可以对每一行内进行高斯消元,那么复杂度是$O(n^4)$,但是发现高斯消元的矩阵中每行只有三个位置有数,这个矩阵叫三对角矩阵,观察这个矩阵,发现可以O(n)消元。复杂度$O(n^2)$

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<cctype>
#include<set>
#include<queue>
#include<vector>
#include<map>
using namespace std;
typedef long long LL;

inline int read() {
    int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
    for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
}

const int mod = 998244353, N = 1005;
const double f31 = 1.0 / 3.0, f32 = 2.0 / 3.0, f41 = 1.0 / 4.0, f43 = 3.0 / 4.0, f38 = 8.0 / 3.0, f23 = 3.0 / 2.0;

double dp[N][N], a[N][N];
int n, m, x, y; 

int ksm(int a,int b) {
    int res = 1;
    while (b) {
        if (b & 1) res = 1ll * res * a % mod;
        a = 1ll * a * a % mod;
        b >>= 1;
    }
    return res;
}

void Make(int i) {
    a[1][1] = f32;
    a[1][2] = -f31;
    a[1][m + 1] = f31 * dp[i + 1][1] + 1;
    a[m][m - 1] = -f31;
    a[m][m] = f32;
    a[m][m + 1] = f31 * dp[i + 1][m] + 1;
    for (int j = 2; j < m; ++j) {
        a[j][j - 1] = -f41;
        a[j][j + 1] = -f41;
        a[j][j] = f43;
        a[j][m + 1] = f41 * dp[i + 1][j] + 1;
    }
}
void pr(int l,int r) {
    for (int i = l; i <= r; ++i) {
        for (int j = 1; j <= m + 1; ++j)
            printf("% .2lf ", a[i][j]);
        puts("");
    }
    puts("");
}
void solve(int i) {
    a[1][1] = 1; a[1][2] *= f23; a[1][m + 1] *= f23;
    for (int j = 2; j < m; ++j) {
        a[j][j - 1] = 0;
        a[j][j + 1] /= (a[j][j] + f41 * a[j - 1][j]);
        a[j][m + 1] += f41 * a[j - 1][m + 1];
        a[j][m + 1] /= (a[j][j] + f41 * a[j - 1][j]);
        a[j][j] = 1;
    }
    a[m][m - 1] = 0;
    a[m][m + 1] += (f31 * a[m - 1][m + 1]);
    a[m][m + 1] /= (a[m][m] + f31 * a[m - 1][m]);
    a[m][m] = 1;

    dp[i][m] = a[m][m + 1];
    for (int j = m - 1; j >= 1; --j) 
        dp[i][j] = a[j][m + 1] - a[j][j + 1] * dp[i][j + 1];
}
int main() {
    n = read(), m = read(), x = read(), y = read();
    if (m == 1) {
        printf("%.10lf", 2.0 * (n - x)); return 0;
    }
    for (int i = n - 1; i >= x; --i) {
        Make(i);
        solve(i);
    }
    printf("%.10lf", dp[x][y]);
    return 0;
}

 

posted @ 2019-03-17 21:46  MJT12044  阅读(195)  评论(0编辑  收藏  举报