codeforce 24D Broken robot 【概率DP】

题目链接:http://codeforces.com/problemset/problem/24/D

题目大意:给出 n*m 的方格地图,机器人在 (x, y),机器人只能向下,向左,向右走,当达到边界时不能走,问到达最后一行需要的期望;

思路:

有两种思路,一个是通过多重的循环精确答案,另一个是找到递推式;

首先对于一个不再边界的点 (i, j),从这里到最后一行需要的期望是由周围决定的;

如果m=1:   dp[i][1] = 1/2 * dp[i + 1][1] + 1/2 * dp[i][1] +1; 

如果 j==1 : dp[i][1] = 1/3 * dp[i + 1][1] + 1/3 * dp[i][2] + 1/3 * dp[i][1] + 1 

如果 j==m :dp[i][m] = 1/3 * dp[i + 1][m] + 1/3 * dp[i][m - 1] + 1/3 * dp[i][m] + 1 

否则 :         dp[i][j] = 1/4 * dp[i + 1][j] + 1/4 * dp[i][j - 1] + 1/4 * dp[i][j] + 1/4 * dp[i][j + 1] + 1

第一种思路(递推式):

首先化简j==1情况的递推式为: dp[i][1] = 1/2 * (3 + dp[i + 1][1]) + 1/2 * dp[i][2]这个式子中dp[ i +1][1]是已知的,但是dp[ i][2]是不确定的,所以可以设 常数A=1/2*(3*dp[ i+1][1]),常数B=1/2,dp[ i][1] = A+B*dp[ i][2];
继续化简 dp[i][2] = (4 + A + dp[i + 1][2]) / 3 - B + dp[i][3] / (3 - B); 
 可以设
A’=(4 + A + dp[i + 1][2]) / 3 - B ,设 B’ = 1 / (3 - B) ; 原式子变成式子变为dp[i][2] = A’ + B’ * dp[i][3]; 
同理,dp[ i][m-1]=A(m-1)+B(m-1)*dp[i][m];
           dp[i][m]=(3+A(m−1)+dp[i+1][m])/(2−B(m−1));

AC代码:

#include<cstring>
#include<string>
#include<cstdio>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<map>
#include<vector>
#include<stack>
#include<queue>
#include<set>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=1e3+10;

double dp[N][N];
double a[N],b[N];

int main()
{
    int n,m;
    while(~scanf("%d %d",&n,&m))
    {
        memset(dp,0,sizeof(dp));
        int x,y;
        scanf("%d %d",&x,&y);
        if(m==1)//注意m=1时,公式不一样,直接能求出答案
        {
            printf("%.10lf\n",2.0*(n-x));
            continue;
        }
        for(int i=1;i<=m;++i)
            dp[n][i]=0.0;
        for(int i=n-1;i>=1;i--)
        {
            a[1]=(3.0+dp[i+1][1])/2.0;
            b[1]=1.0/2;
            for(int j=2;j<m;j++)
            {
                a[j]=(4+a[j-1]+dp[i+1][j])/(3-b[j-1]);
                b[j]=1.0/(3.0-b[j-1]);
            }
            dp[i][m]=(3+a[m-1]+dp[i+1][m])/(2-b[m-1]);
            for(int j=m-1;j>=1;j--)
            {
                dp[i][j]=a[j]+b[j]*dp[i][j+1];
            }
        }
        printf("%.10lf\n",dp[x][y]);
    }
    return 0;
}

第二种:

首先化简j==1情况的递推式为: dp[i][1] = 1/2 * (3 + dp[i + 1][1]) + 1/2 * dp[i][2].  这个式子中dp[ i +1][1]是已知的,但是dp[ i][2]是不确定的,但是我们可以多循环就此这个步骤,答案就能精确了;

AC代码:

//#include<bits/stdc++.h>
#include<cstring>
#include<string>
#include<cstdio>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<map>
#include<vector>
#include<stack>
#include<queue>
#include<set>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=1e3+10;

double dp[N][N];
double a[N],b[N];

int main()
{
    int n,m,x,y;
    while(~scanf("%d %d %d %d",&n,&m,&x,&y))
    {
        memset(dp,0,sizeof(dp));
        for(int i=n-1;i>=1;i--)
        {
            for(int t=1;t<=100;++t)
            {
                for(int j=1;j<=m;++j)
                {
                    if(m==1)
                        dp[i][j]=dp[i+1][j]+2.0;
                    else if(j==1)
                        dp[i][j]=(dp[i+1][j]+dp[i][j+1]+3)/2.0;
                    else if(j==m) 
                        dp[i][j]=(dp[i+1][j]+dp[i][j-1]+3)/2.0;
                    else 
                        dp[i][j]=(dp[i+1][j]+dp[i][j-1]+dp[i][j+1]+4)/3.0;
                }
            }
        }
        printf("%.10lf\n",dp[x][y]);
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值