CF24D Broken robot
作者:互联网
思路
一道典型的高斯消元
的期望DP
通过朴素的思考,我们可以获得如下的转移方程
\[f_{i,j}=p_{i,j-1}\times(f_{i,j-1}+1)+p_{i,j}\times(f_{i,j}+1)+p_{i,j+1}\times(f_{i,j+1}+1)+p_{i+1,j}\times(f_{i+1,j}+1) \](我们这里采用的是老套路逆推,而要注意到在边界的点移动的概率可能不为 \(\frac1 4\))
乍一看,则不就是简简单单的高消嘛
然后看一下数据范围,好家伙 \(O((nm)^3)\) 怎么可能能过
但再仔细看,每个方程最多只有三个系数不为 \(0\)
而且第 \(i\) 行的转移和第 \(i-1\) 行没有关系,那我们就考虑分开每行高消!
这样我们每次其实就是做一个带状矩阵的高斯消元
时间复杂度为 \(O(mn)\)
代码
#include<iostream>
#include<fstream>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#define LL long long
inline int reads()
{
int sign = 1, re = 0; char c = getchar();
while(c < '0' || c > '9'){if(c == '-') sign = -1; c = getchar();}
while('0' <= c && c <= '9'){re = re * 10 + (c - '0'); c = getchar();}
return sign * re;
}
int n, m, x, y;
double f[1005];
double a[1005][1005];
inline void Gauss()
{
for(int i = 1; i <= m; i++)
{
double mul = a[i + 1][i] / a[i][i];
for(int j = i; j < i + 2; j++)
a[i + 1][j] -= mul * a[i][j];
a[i + 1][m + 1] -= mul * a[i][m + 1];
}
for(int i = m; i >= 1; i--)
{
f[i] = a[i][m + 1];
f[i] -= a[i][i + 1] * f[i + 1];
f[i] /= a[i][i];
}
}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("test.in", "r", stdin);
freopen("test.out", "w", stdout);
#endif
n = reads(), m = reads(), x = reads(), y = reads();
if(m == 1)
{
printf("%d", (n - x) << 1);
return 0;
}
n -= x;
while(n--)
{
for(int i = 1; i <= m; i++)
{
if(i == 1)
a[i][i - 1] = 0, a[i][i] = 2.0 / 3.0, a[i][i + 1] = -1.0 / 3.0, a[i][m + 1] = f[i] / 3.0 + 1.0;
else if(i == m)
a[i][i - 1] = -1.0 / 3.0, a[i][i] = 2.0 / 3.0, a[i][i + 1] = 0, a[i][m + 1] = f[i] / 3.0 + 1.0;
else
a[i][i - 1] = -0.25, a[i][i] = 0.75, a[i][i + 1] = -0.25, a[i][m + 1] = f[i] * 0.25 + 1.0;
}
Gauss();
}
printf("%.4lf", f[y]);
return 0;
}
标签:sign,robot,times,Broken,reads,freopen,CF24D,include,高斯消 来源: https://www.cnblogs.com/zuytong/p/16081834.html