DP专题9 终 | 机器人 HDU -4576(概率DP)

本篇是一个概率DP问题,也是DP专题的最后一篇,概率DP是DP中一个较为特殊的算法问题,混合了概率这个元素在里面,需要对概率有比较好的理解。

 

概率DP问题很多时候会和复杂的概率计算混合在一起,要想更好的掌握只能多做相关题目,熟练掌握概率相关的知识也是很重要的一步。

概况DP是混合了概率计算和DP结构的一种算法。

本篇是一个入门题目,希望能够让没接触过概率DP的同学有个简单了解。

 

Problem Description

Michael has a telecontrol robot. One day he put the robot on a loop with n cells. The cells are numbered from 1 to n clockwise.

麦克有一个遥控机器人,他把机器人放在一个圆盘上,圆盘分为n格,如下图所示,格子从1标记到n。
 



At first the robot is in cell 1. Then Michael uses a remote control to send m commands to the robot. A command will make the robot walk some distance. Unfortunately the direction part on the remote control is broken, so for every command the robot will chose a direction(clockwise or anticlockwise) randomly with equal possibility, and then walk w cells forward.

 

 

一开始机器人在格子1,麦克通过遥控给机器人发送m条指令。指令能够让机器人移动一段距离,机器人等概率的顺时针或者逆时针进行移动,会向前移动w个格子。


Michael wants to know the possibility of the robot stopping in the cell that cell number >= l and <= r after m commands.

 

麦克想知道机器人停留在[l, r]区间的概率。

 

Input

There are multiple test cases. 
Each test case contains several lines.
The first line contains four integers: above mentioned n(1≤n≤200) ,m(0≤m≤1,000,000),l,r(1≤l≤r≤n).

 

第一行:格子数n,指令数m,区间l和r


Then m lines follow, each representing a command. A command is a integer w(1≤w≤100) representing the cell length the robot will walk for this command.  

 

接下来是m条指令,每条指令指的是机器人会移动m个格子。


The input end with n=0,m=0,l=0,r=0. You should not process this test case.

 

最后一行4个0表示结束

 

Output

For each test case in the input, you should output a line with the expected possibility. Output should be round to 4 digits after decimal points.

 

 

Sample Input


 

3 1 1 2
1
5 2 4 4
1
2
0 0 0 0

 

Sample Output


 

0.5000
0.2500

 

这是一个比较简单的概率DP题目,只需要注意几个点就能很快写出代码。

如下图中的位置1,位置1的概率为1.0,如果第一步走1格,则对于节点2来说,可能有1号位置和3号位置能够到达2,到达2的概率即为p(1)*0.5+p(3)*0.5,p(n)表示位置n的概率。

 

 

每一次迭代,都是如此往复,最后的结果就是将区间l/r的所有概率加起来。

 

注意可以使用滚动数组来进行空间优化。

 

0^1=1 1^1=0,如此循环替换。

 

源代码:

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;

double dp[2][220];

int main() {
    int n, m, l, r;

    while (scanf("%d%d%d%d", &n, &m, &l, &r) == 4) {
        if (n == 0 && m == 0 && l == 0 && r == 0)
            break;

        // 初始化位置0的概率为1
        dp[0][0] = 1;

        //n个格子 
        for (int i = 1; i < n; i++)
            dp[0][i] = 0;

        int now = 0;

        while (m--) {
            // 前进格子数
            int v;
            scanf("%d", &v);

            //对于每一格格子进行计算 
            for (int i = 0; i < n; i++){
                // 注意是环状,需要取余计算
                dp[now ^ 1][i] = 0.5 * dp[now][(i - v + n) % n] + 0.5 * dp[now][(i + v) % n];
            }

            now ^= 1;
        }
        double ans = 0;
        for (int i = l - 1; i < r; i++)
            ans += dp[now][i];

        printf("%.4lf\n", ans);
    }
    return 0;
}

个人公众号(acm-clan):ACM算法日常

专注于基础算法的研究工作,深入解析ACM算法题,五分钟阅读,轻松理解每一行源代码。内容涉及算法、C/C++、机器学习等。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章