zoukankan      html  css  js  c++  java
  • 【题解】CF24D Broken Robots(收敛性)

    【题解】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 ]

    写成矩阵

    [egin{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)次就好了。此处的分析是错误的,请高手说明一下QAQ。注意,这里的"概率函数的收敛"性是抽出一行看的,不能在转移的时候把自己的(0.25)和上一行的(0.25l)加进来,不然显然是个发散的函数。

    为了方便统计答案,我们反着dp,毕竟从最后一行到起点的期望步数=从起点到最后一行的期望步数。

    (dp(i,j))表示从最后一行到这一点((i,j))的期望步数。

    转移:

    [dp(i,j)=1/dr[i][j] imes (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
    
    
  • 相关阅读:
    STL笔记之【map之总概】
    STL笔记之set
    Effective C++笔记之Item49【了解new-handler的行为】
    明成软件条形码打印设置
    将Excel数据导入到SqlServer及导入时数据类型转换失败解决方案
    远程桌面无法复制粘贴传输文件解决办法
    DELPHI如何读取cxcheckcombobox中的值
    Delphi 插入Excel图片和值
    SQL 查询语句先执行 SELECT?
    Linux之xargs命令传递参数的一个过滤器
  • 原文地址:https://www.cnblogs.com/winlere/p/10958862.html
Copyright © 2011-2022 走看看