HDU-4487 Maximum Random Walk(概率dp)

题目链接

题目大意

  随机游走问题的变形,给你每一步向左走和向右走的概率,问第n步走到的最远距离的期望。

解题思路

  直接求期望不太好做,不过可以先求出概率,设\(dp[i][j][k]\)表示第i步在j位置,最远走到了k位置,那么第i+1步可能是第i步向左走,向右走,原地不动三种情况转移过来的。我们分类讨论一下。
  如果向右走的话,可能下一步走的位置比原来更远,说明j+1>k,我们可以更新\(dp[i+1][j+1][j+1] = dp[i][j][k] \times p_r\),也可能没有比原来的远,这时候最远的位置仍是k,所以更新\(dp[i+1][j+1][k] = dp[i][j][k] \times p_r\)
  如果向左走,显然只有一种情况,\(dp[i+1][j-1][k] = dp[i][j][k] \times p_l\)
  如果原地不动的话,也是一种情况,\(dp[i+1][j][k] = dp[i][j][k] \times 1-(p_l+p_r)\)
  因为题目有内存限制,而且第一维转移的时候只与下一个状态有关系,所以可以用滚动数组省下空间,还有一点需要注意的是,有走到负数的情况,所以对于数组后两维整体+100。

代码

#include<bits/stdc++.h>
#define endl '\n'
#define x first
#define y second
#define clr(arr,a) memset(arr, a, sizeof(arr))
#define IOS ios::sync_with_stdio(false)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> P;
typedef pair<ll, int> Pll;
const double pi = acos(-1.0);
const double eps = 1e-8;
const int MOD = 11380;
const int INF = 0x3f3f3f3f;
const int maxn = 2e2+10;
double dp[2][maxn][maxn];
const double fx = 100;
int main(void) {
    int __; cin >> __;
    while(__--) {
        int k, n; double pl, pr; cin >> k >> n >> pl >> pr;
        clr(dp, 0);
        dp[0][100][100] = 1;
        for (int i = 0; i<=n; ++i) {
            for (int j = 100-i; j<=100+i; ++j)
                for (int k = 100-i; k<=100+i; ++k) {
                    int nxt = (i+1)&1;
                    dp[nxt][j][k] = 0;
                }
            for (int j = 100-i; j<=100+i; ++j)
                for (int k = 100-i; k<=100+i; ++k) {
                    if (j>k) continue;
                    int nxt = (i+1)&1;
                    int now = i&1;
                    if (j+1<=k) dp[nxt][j+1][k] += dp[now][j][k]*pr;
                    if (j+1>k) dp[nxt][j+1][j+1] += dp[now][j][k]*pr;
                    if (j) dp[nxt][j-1][k] += dp[now][j][k]*pl;
                    dp[nxt][j][k] += dp[now][j][k]*(1-pl-pr);
                }
        }
        double sum = 0;
        for (int i = 100-n; i<=100+n; ++i)
            for (int j = 100-n; j<=100+n; ++j) {
                sum += (j-100)*dp[n&1][i][j];
            }
        printf("%d %.4f\n", k, sum);
    }
    return 0;
}

posted @ 2021-04-28 20:50  shuitiangong  阅读(120)  评论(0编辑  收藏  举报