HDU-4576-Robot
传送门
这道题是一道入门级dp,归属为概率dp。
题目大意:给你一个环,环上面有n个单位,有一个机器人,它的初始位置是在1的位置,这个机器人可以随机向前或者向后走,现在给你走的步数,问现在在某个区间段[l, r]中的概率是多少。
本题思路:我们用dp[0][]和dp[1][]来表示相对的前后状态的概率值,这也算一个状态压缩了,滚动数组。
我们初始化dp[0][0] = 1,表示初始位置的概率为1。
然后我们通过遍历,来记录当前机器人走到某处的概率。
每次给走的步数,我们都需要初始化要记录的数组。所以我们用dp[][]是否等于0来判断是否到达这个位置,因为这恰好符合异或运算的性质,所以我们这里用到了异或运算。
初始化t = 0,每次进行t ^= 1操作来进行下一次概率计算。
到最后要求区间和的概率。
因为我们最后一次状态就保存在dp[t][]中,所以我们求一下[l, r]区间的和即可。
最后记得保留四位小数哦。
这道题卡时间空间~
代码部分:
#include <bits/stdc++.h>
using namespace std;
const int N = 2e2 + 10;
double dp[2][N];
int n, m, l, r;
int main()
{
while (scanf ("%d%d%d%d", &n, &m, &l, &r) && n + m + l + r)
{
if (!n && !m && !l && !r)
{
break;
}
int t = 0;
dp[0][0] = 1;
for (int i = 1; i <= n; i++)
{
dp[0][i] = 0;
}
while (m--)
{
int a;
scanf ("%d", &a);
for (int i = 0; i < n; i++)
{
dp[t ^ 1][i] = 0;
}
for (int i = 0; i < n; i++)
{
if (dp[t][i])
{
dp[t ^ 1][(i + a + n) % n] += 0.5 * dp[t][i];
dp[t ^ 1][(i - a + n) % n] += 0.5 * dp[t][i];
}
}
t ^= 1;
}
double ans = 0;
for (int i = l - 1; i < r; i++)
{
ans += dp[t][i];
}
printf ("%.4f\n", ans);
}
return 0;
}