ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

$CF24D\ Broken Robot\ DP+$高斯消元

2019-06-13 15:52:54  阅读:301  来源: 互联网

标签:int 机器人 Broken CF24D include 递推 步数 高斯消 define


Luogu

 

Description

你收到的礼物是一个非常聪明的机器人,行走在一块长方形的木板上.不幸的是,你知道它是坏的,表现得相当奇怪(随机).该板由n行和m列的单元格组成.机器人最初是在i行和j列的某个单元格上.然后在每一步机器人可以到另一个单元.目的是去底层(n次)行.机器人可以停留在当前单元,向左移动,向右边移动,或者移动到当前下方的单元.如果机器人在最左边的列不能向左移动,如果它是在最右边的列不能向右移动.在每一步中,所有可能的动作都是同样可能的.返回步的预期数量达到下面的行.

 

Sol

这题和传纸条有点类似,不同的是机器人既能向左走又能向右走,而传纸条只能向右传.

f[i][j]表示从(i,j)走到最后一行所需要的期望步数

f[i][1]=1/3(f[i][1]+f[i][2]+f[i+1][1])+1

f[i][m]=1/3(f[i][m]+f[i][m-1]+f[i+1][m])+1

(j!=1&&j!=m)f[i][j]=1/4(f[i][j]+f[i][j-1]+f[i][j+1]+f[i+1][j])+1

部分状态之间可以互相转移互相影响,并不能满足DP的无后效性

所以不能线性递推,要用高斯消元直接求出状态转移方程的解

需要注意的是m=1的情况要特判

m=3时,系数矩阵如下:

-2/3  1/3    0

1/4    1/4    1/4

0        1/3    -2/3

值得一提的是,我们用f[i][j]表示从(i,j)走到最后一步的期望步数,按照行号倒序进行递推,而不是用f[i][j]表示从(x,y)到(i,j)的期望步数并正序递推.原因是,若正序递推,则还须求出(x,y)到最后一行每一个位置的概率p[n][j],计算Σp[n][j]*f[n][j]才能得到答案,较为复杂.

事实上,很多数学期望DP都会采取倒推的方式执行.

 

Code

关于代码实现其实还有几个值得注意的地方

1.f[i][j]数组可以滚动优化

2.因为要多次解方程组,很多人可能会每次都初始化a数组(系数矩阵).其实没有必要,只要初始化一次,并且同时记录一下c[i]=a[i+1][i]/a[i][i]就好了(没写code这句话可能暂时看不懂,看下code就会懂了鸭QwQ)

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #define Rg register
 5 #define il inline
 6 #define db double
 7 #define ll long long
 8 #define mem(a,b) memset(a,b,sizeof(a));
 9 #define go(i,a,b) for(Rg int i=a;i<=b;++i)
10 #define yes(i,a,b) for(Rg int i=a;i>=b;--i)
11 using namespace std;
12 il int read()
13 {
14     int x=0,y=1;char c=getchar();
15     while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();}
16     while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+c-'0';c=getchar();}
17     return x*y;
18 }
19 const int N=1001;
20 int n,m,x,y;
21 db a[N][N],b[N],f[N],c[N];
22 il void init_a()
23 {
24     if(m==1){a[1][1]=(db)-1.0/2;return;}
25     a[1][1]=(db)-2.0/3;a[1][2]=(db)1.0/3;
26     a[m][m-1]=(db)1.0/3;a[m][m]=(db)-2.0/3;
27     go(i,2,m-1)a[i][i-1]=(db)1.0/4,a[i][i]=(db)-3.0/4,a[i][i+1]=(db)1/4;
28     go(i,1,m)
29     {
30         c[i]=a[i+1][i]/a[i][i];
31         a[i+1][i]-=c[i]*a[i][i];
32         a[i+1][i+1]-=c[i]*a[i][i+1];
33     }
34 }
35 il void init_b()
36 {
37     if(m==1){b[1]=(db)-f[1]/2-1;return;}
38     b[1]=-(db)f[1]/3-1;b[m]=-(db)f[m]/3-1;
39     go(i,2,m-1)b[i]=-(db)f[i]/4-1;
40 }
41 il void calc()
42 {
43     go(i,1,m){db t=c[i];b[i+1]-=t*b[i];}
44     f[m]=b[m]/a[m][m];
45     yes(i,m-1,1)f[i]=(b[i]-f[i+1]*a[i][i+1])/a[i][i];
46 }
47 int main()
48 {
49     n=read(),m=read(),x=read(),y=read();//m==1 special case !
50     init_a();
51     yes(i,n-1,x){init_b();calc();}
52     printf("%.10lf",f[y]);
53     return 0;
54 }
View Code

 

标签:int,机器人,Broken,CF24D,include,递推,步数,高斯消,define
来源: https://www.cnblogs.com/forward777/p/11016856.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有