【题解】CF24D Broken Robots
http://codeforces.com/problemset/problem/24/D
解1
获得一个比较显然的转移式子
\(dp(i,j)\)代表在\((i,j)\)坐标需要期望的走的次数
\[
dp(i,j)=0.25(1+dp(i-1,j)+dp(i,j-1)+dp(i,j+1))
\]
然而我们可以发现这个式子不满足无后效性..也找不到一种合适的顺序DP。
我们发现可以高斯消元,但是\(O(n^4)\)的复杂度我们接受不了。
式子里面的\(dp(i-1,j)\)是上一行的事情,不需要考虑,直接转移即可,我们把\(dp(i,j)\)抽象为\(x_j\)
那么我们考虑的是。
\[
x_j=0.25(1+l_j+x_{j-1}+x_{j+1})
\]
写成划一下
\[
-0.25x_{j-1}+x_j-0.25x_{j+1}=0.25l_j+0.25
\]
写成矩阵
\[
\begin{pmatrix}
1&-0.25&0& 0&0&0&0.25l_1+0.25
\-0.25&1&-0.25& 0&0&0&0.25l_2+0.25
\0&-0.25&1&-0.25&0&0&0.25l_3+0.25
\0&0&-0.25&1&-0.25&0&0.25l_4+0.25
\0&0&0&-0.25&1&-0.25&0.25l_5+0.25
\0&0&0&0&-0.25&1&0.25l_6+0.25
\end{pmatrix}
\]
魔改一下高斯消元即可。
解2
众所周知,概率函数具有收敛性。 并且是指数地收敛的。又因为期望的式子里有概率作为因子,所以它应该是收敛的。(其实不是应该!是一定!若概率收敛则期望收敛(特殊情况除外),具体证说明可以把概率和随机变量分开DP!)
好,既然我们已经知道了这个函数具有收敛性,那么我们就让他在每一行就多转移几次就好了。具体操作就是让每个点按照顺序每次从左边转移过来一次,从右边转移过来一次。重复这个步骤随便多少次就好了。
由于精度只要\(10^{-4}\),我们只需要\(\log_{\frac 1 3}10^{-4}=9\)次就好了。注意,这里的"概率函数的收敛"性是抽出一行看的,不能在转移的时候把自己的\(0.25\)和上一行的\(0.25l\)加进来,不然显然是个发散的函数。
为了方便统计答案,我们反着dp,毕竟从最后一行到起点的期望步数=从起点到最后一行的期望步数。
\(dp(i,j)\)表示从最后一行到这一点\((i,j)\)的期望步数。
转移:
\[
dp(i,j)=1/dr[i][j]\times (dp[i+1][j]+dp[i][j-1,j,j+1])+1
\]
//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; typedef long long ll;
inline int qr(){
register int ret=0,f=0;
register char c=getchar();
while(c<48||c>57)f|=c==45,c=getchar();
while(c>=48&&c<=57) ret=ret*10+c-48,c=getchar();
return f?-ret:ret;
}
const int maxn=1e3+5;
typedef long double lb;
lb dp[maxn][maxn],ans;
const lb qt[]={0,(lb)1.0/1,(lb)1.0/2,(lb)1.0/3,(lb)1.0/4};
int cnt;
int n,m;
int x,y;
int main(){
n=qr();m=qr();
x=qr();y=qr();
const int lit=50000000/(m)/(n-x+1);
for(register int t=n-1;t>=x;--t){
for(register int t0=1;t0<=lit;++t0){
if(m>1)
dp[t][1]=qt[3]*(dp[t+1][1]+dp[t][2]+dp[t][1])+1,dp[t][m]=qt[3]*(dp[t+1][m]+dp[t][m-1]+dp[t][m])+1;
if(m==1) dp[t][1]=qt[2]*(dp[t][1]+dp[t+1][1])+1;
for(register int i=2;i<m;++i)
dp[t][i]=qt[4]*(dp[t+1][i]+dp[t][i-1]+dp[t][i]+dp[t][i+1])+1;
}
}
cout.precision(10);
cout<<dp[x][y]<<endl;
return 0;
}
//18.0038068653
原文地址:https://www.cnblogs.com/winlere/p/10958862.html