[CF24D]Broken Robot

题面:Luogu
题解:期望dp+gauss消元
真是古老的题目啊
dp方程很显然:设\(dp_{i,j}\)表示\((i,j)\)走到最后一行的期望步数
第一列时\(dp_{i,1}=\frac{1}{3}(f_{i,1}+f_{i,2}+f_{i+1,1})+1\)
最后一列时\(dp_{i,m}=\frac{1}{3}(f_{i,m}+f_{i,m-1}+f_{i+1,m})+1\)
其他列\(dp_{i,j}=\frac{1}{4}(f_{i,j}+f_{i,j-1}+f_{i,j+1}+f_{i+1,j})+1\)
边界:最后一行\(dp_{n,i}=0\)
于是从第\(n\)行向第1行递推,此时\(dp_{i+1,j}\)都为已知
于是有系数矩阵
\[ \left[ \begin{matrix} -\frac{2}{3} & \frac{1}{3} & 0 & 0 & 0 \\ \frac{1}{4} & -\frac{3}{4} & \frac{1}{4} & 0 & 0 \\ 0 & \frac{1}{4} & -\frac{3}{4} & \frac{1}{4} & 0 \\ 0 & 0 & \frac{1}{4} & -\frac{3}{4} & \frac{1}{4} \\ 0 & 0 & 0 & \frac{1}{3} & -\frac{2}{3} \\ \end{matrix} \right] \]
于是我们可以把它消成一个上三角矩阵,具体看代码即可
注意\(m=1\)时要特判一下

#include<bits/stdc++.h>
using namespace std;
inline void read(int& x)
{
    x = 0; char c = getchar();
    while (!isdigit(c)) c = getchar();
    while (isdigit(c)) x = x * 10 + c - '0', c = getchar();
}
#define maxn 1005
#define db double
db a[maxn][maxn], b[maxn], f[maxn];//系数,常数,下一行的dp值
int n, m, x, y;
inline void init()
{
    if (m == 1)
    {
        a[1][1] = -1.0 / 2.0;
        b[1] = -f[1] / 2.0 - 1;
        return;
    }
    a[1][1] = a[m][m] = -2.0 / 3.0;
    a[1][2] = a[m][m - 1] = 1.0 / 3.0;
    b[1] = -f[1] / 3.0 - 1, b[m] = -f[m] / 3.0 - 1;
    for (int i = 2; i < m; ++i)
    {
        a[i][i - 1] = a[i][i + 1] = 1.0 / 4.0;
        a[i][i] = -3.0 / 4.0;
        b[i] = -f[i] / 4.0 - 1;
    }
}
inline void gauss()
{
    for (int i = 1; i < m; ++i)
    {
        db tp = a[i + 1][i] / a[i][i];
        a[i + 1][i] = 0;
        a[i + 1][i + 1] -= tp * a[i][i + 1];
        b[i + 1] -= tp * b[i];
    }
    f[m] = b[m] / a[m][m];
    for (int i = m - 1; i; --i)
        f[i] = (b[i] - a[i][i + 1] * f[i + 1]) / a[i][i];
}
int main()
{
    read(n), read(m), read(x), read(y);
    for (int i = n - 1; i >= x; --i) init(), gauss();
    printf("%.10lf", f[y]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/123789456ye/p/12536902.html
今日推荐