CodeForces 24 D.Broken robot(概率DP+高斯消元)

本文介绍了一种算法,用于计算机器人在一个n×m的矩阵区域内,从指定起点到达最后一行的期望步数。该算法考虑了机器人可以进行的四种移动方式,并提供了详细的数学推导过程及代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description

给出一个n×mn×m的矩阵区域,一个机器人初始在第xx行第y列,每一步机器人会等概率的选择停在原地,左移一步,右移一步,下移一步,如果机器人在边界则不会往区域外移动,问机器人到达最后一行的期望步数

Input

第一行两个整数n,mn,m表示矩阵行列数,之后输入两个整数x,yx,y表示机器人初始位置(1n,m1000,1xn,1ym)(1≤n,m≤1000,1≤x≤n,1≤y≤m)

Output

输出机器人走到最后一行的期望步数

Sample Input

10 10
10 4

Sample Output

0.0000000000

Solution

m=1m=1时每次1212概率不动,1212概率下移一步,答案显然为2(nx)2⋅(n−x)

dp[i]][j]dp[i]][j]表示机器人从第ii行第j列出发到达最后一行的期望步数,显然dp[n][j]=0,1jmdp[n][j]=0,1≤j≤m

由机器人等概率选择停在原地,左移一步,右移一步,下移一步有转移:

dp[i][1]=1+13dp[i][1]+13dp[i][2]+13dp[i+1][1]dp[i][1]=1+13dp[i][1]+13dp[i][2]+13dp[i+1][1]

dp[i][j]=1+14dp[i][j]+14dp[i][j1]+14dp[i][j+1]+14dp[i+1][j],1<j<mdp[i][j]=1+14dp[i][j]+14dp[i][j−1]+14dp[i][j+1]+14dp[i+1][j],1<j<m

dp[i][m]=1+13dp[i][m]+13dp[i][m1]+13dp[i+1][m]dp[i][m]=1+13dp[i][m]+13dp[i][m−1]+13dp[i+1][m]

写成矩阵形式

dp[i][1]12dp[i][2]=32+12dp[i+1][1]dp[i][1]−12dp[i][2]=32+12dp[i+1][1]

14dp[i][j1]+34dp[i][j]14dp[i][j+1]=1+14dp[i+1][j],1<j<m−14dp[i][j−1]+34dp[i][j]−14dp[i][j+1]=1+14dp[i+1][j],1<j<m

12dp[i][m1]+dp[i][m]=32+12dp[i+1][m]−12dp[i][m−1]+dp[i][m]=32+12dp[i+1][m]

由于转移矩阵是一个三对角矩阵,O(n)O(n)即可消元,即通过第一行的dp[i][1]+a[1]dp[i][2]=b[1]dp[i][1]+a[1]⋅dp[i][2]=b[1]和第二行消去dp[i][1]dp[i][1]得到dp[i][2]+a[2]dp[i][3]=b[2]dp[i][2]+a[2]⋅dp[i][3]=b[2],以此类推求出dp[i][j]+a[j]dp[i][j+1]=b[j],1j<mdp[i][j]+a[j]⋅dp[i][j+1]=b[j],1≤j<m,用dp[i][m1]+a[m1]dp[i][m]=b[m1]dp[i][m−1]+a[m−1]⋅dp[i][m]=b[m−1]以及最后一个等式求出dp[i][m]dp[i][m],然后从后往前通过dp[i][j]=b[j]a[j]dp[i][j+1]dp[i][j]=b[j]−a[j]⋅dp[i][j+1]求出所有的dp[i][j]dp[i][j]即可,时间复杂度O(n2)O(n2)

Code

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f,maxn=1005;
int n,m,x,y;
double a[maxn],b[maxn],dp[maxn][maxn];
int main()
{
    scanf("%d%d%d%d",&n,&m,&x,&y);
    if(m==1)printf("%.5f\n",2.0*(n-x));
    else
    {
        for(int j=1;j<=m;j++)dp[n][j]=0;
        for(int i=n-1;i>=x;i--)
        {
            a[1]=-0.5;b[1]=1.5+0.5*dp[i+1][1];
            for(int j=2;j<m;j++)
            {
                b[j]=1.0+0.25*dp[i+1][j]+0.25*b[j-1];
                a[j]=-0.25;
                double temp=0.75+0.25*a[j-1];
                a[j]/=temp;b[j]/=temp;
            }
            dp[i][m]=(3.0+dp[i+1][m]+b[m-1])/(2.0+a[m-1]);
            for(int j=m-1;j>=1;j--)dp[i][j]=b[j]-a[j]*dp[i][j+1];
        }
        printf("%.5f\n",dp[x][y]);
    }
    return 0;
}
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值