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;
}