题目大意:有一个环,有n个格子,编号为1~n; 一开始1的位置上有一个机器人,每次给他一个指令m,它移动m距离,但是它等可能的向左或者向右。求m条指令之后在l和r之间的可能性。
解题思路:这个题卡时间卡的非常紧,超时了两次。简直崩溃,但是题目本身不难。每读取一个指令,将数组内概率更新,每个位置都可能向前或者向后x,因此把自己的概率乘以0.5加给那个格子即可。但是每次都应该初始化为零,因为这个指令之后,自己格子原来的概率已经没有了,即上次没停留,只是执行到这一次时在这里的概率。因此还需要一个数组保存上次格子的概率。因为卡时间,所以用滚动时数组。
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int main()
{
int n, m, l, r, x;
double dp[2][205];
while(scanf("%d%d%d%d", &n, &m, &l, &r) == 4 && n+m+l+r)
{
memset(dp, 0, sizeof(dp));
dp[0][1] = 1.0;
bool k = 1;
for(int i=0; i<m; i++)
{
scanf("%d", &x);
k = k ^ 1;//异或1,使k在1和0来回变换达到滚动的目的
for(int j=1; j<=n; j++) dp[!k][j] = 0;//!k则是保存本次的概率。k是上次的概率
for(int j=1; j<=n; j++)
{
if(!dp[k][j]) continue;
dp[!k][ (j+x-1)%n+1 ] += 0.5 * dp[k][j];
dp[!k][ (j+n*100-x-1)%n+1 ] += 0.5 * dp[k][j];
}
}
double ans = 0.0;
for(int i=l; i<=r; i++) ans += dp[!k][i];
printf("%.4f\n", ans);
}
return 0;
}