【算法题】随机的机器人

随机的机器人

有一条无限长的纸带,分割成一系列的格子,最开始所有格子初始是白色。现在在一个格子上放上一个萌萌的机器人(放上的这个格子也会被染红),机器人一旦走到某个格子上,就会把这个格子涂成红色。现在给出一个整数n,机器人现在会在纸带上走n步。每一步,机器人都会向左或者向右走一个格子,两种情况概率相等。机器人做出的所有随机选择都是独立的。现在需要计算出最后纸带上红色格子的期望值。

输入描述:
输入包括一个整数n(0 ≤ n ≤ 500),即机器人行走的步数。

输出描述:
输出一个实数,表示红色格子的期望个数,保留一位小数。

输入例子:
4

输出例子:
3.4


分析:概率期望问题感觉没法下手,不知道动态规划还能这么玩

dp[i][j][k] 表示走了 i 步后,纸带上有 j 个红色格子时,机器人位于 k 个红色格子上的概率

dp[0][1][1]=1

则dp[i][j][k]的概率会转移到dp[i+1][][]的两个位置上:

  • 机器人位于最左边红格子:
    dp[i][j][1]/2 的概率会转移到 dp[i+1][j+1][1]
    dp[i][j][1]/2 的概率会转移到 dp[i+1][j][2]

  • 机器人位于最右边红格子:
    dp[i][j][j]/2 的概率会转移到 dp[i+1][j+1][j+1]
    dp[i][j][j]/2 的概率会转移到 dp[i+1][j][j1]

  • 其余情况:
    dp[i][j][k]/2 的概率会转移到 dp[i+1][j][k+1]
    dp[i][j][k]/2 的概率会转移到 dp[i+1][j][k1]

最终走完n步后,加权求和即为期望

注意:数组如果过大,直接在栈分配 牛客网会提示段错误


#include 
#include 
#include 
#include 
#include 
using namespace std;
#define debug_

vector<vector<vector<double>>> dp;
vector<double> vec;
vector<vector<double>> vec_2;
//dp[2][503][503]
double func(int n)
{
    vec.resize(503);
    vec_2.resize(503, vec);
    dp.resize(2, vec_2);

    dp[0][1][1] = 1;
    int prestep, curstep;
    for (auto i = 1; i <= n; ++i)
    {
        prestep = (i - 1) % 2;
        curstep = i % 2;

        for (auto j = 0; j <= n + 1; ++j)
            for (auto k = 0; k <= n + 1; ++k)
                dp[curstep][j][k] = 0;

        for (auto j = 0; j <= n + 1; ++j)
            for (auto k = 1; k <= n + 1; ++k)
            {
                if (k == 1)//向左
                {
                    dp[curstep][j + 1][k] += dp[prestep][j][k] / 2.;
                }
                else
                {
                    dp[curstep][j][k - 1] += dp[prestep][j][k] / 2.;

                }

                if (k == j)//向右
                {
                    dp[curstep][j + 1][k + 1] += dp[prestep][j][k] / 2.;
                }
                else
                {
                    dp[curstep][j][k + 1] += dp[prestep][j][k] / 2.;
                }
            }
    }
    curstep = n % 2;
    double result(0);
    for (auto j = 0; j <= n + 1; ++j)
    {
        double a(0);
        for (auto i = 0; i < 501; ++i)
        {
            a += dp[curstep][j][i];
        }
        result += (double)j*accumulate(dp[curstep][j].begin(), dp[curstep][j].end(), 0.);
    }

    return result;
}

int main()
{
    int n;
#ifdef debug_
    n = 500;
#else
    cin >> n;
#endif
    cout <<  fixed << setprecision(1)<< func(n);

    return 0;
}

你可能感兴趣的:(动态规划,牛客网模拟笔试)