3 1 1 2 1 5 2 4 4 1 2 0 0 0 0
0.5000 0.2500
题意为有编号1-N的格子围城一个圈,一开始机器人站在1号格子,有M个命令,每个命令机器人走W格,可以顺时针也可以逆时针,问M个命令后,机器人站在格子[L,R] 的概率是多少.
想法大体为暴力计算出M个命令后,每个格子上机器人在的概率,那么 P[ L ] + P[ L+1] + P[ L+2] +............P[R] 即为所求
用dp[i][j] ,表示第i个命令后机器人站在j位置的概率
因为命令数m,0≤m≤1,000,000,不可能开出这么大的数组,又因为第i个命令后机器人所在位置的概率只与第i-1个命令后的机器人所在位置有关,所以可以用滚动数组,dp [2] [j]来表示。滚动数组要求当前状态只和前一个状态有关系,和更早之前的状态没关系,所以之前保存的数空间可以覆盖,重新利用,这样就可以降低空间复杂度,但时间复杂度不变。
滚动数组详解:http://blog.csdn.net/niushuai666/article/details/6677982
代码:
#include <iostream> #include <stdio.h> #include <iomanip> #include <string.h> using namespace std; double dp[2][210]; int main() { int n,m,l,r,cm; while(scanf("%d%d%d%d",&n,&m,&l,&r)!=EOF) { if(n==0&&m==0&&l==0&&r==0) break; int d=0; for(int i=1;i<n;i++) dp[d][i]=0; dp[0][0]=1; while(m--) { scanf("%d",&cm); for(int i=0;i<n;i++) dp[d^1][i]=0;//新状态下每个位置的概率都为0 for(int i=0;i<n;i++) { if(dp[d][i]==0)//加上这一句就不超时了 continue; dp[d^1][(i+cm)%n]+=0.5*dp[d][i]; dp[d^1][(i-cm+n)%n]+=0.5*dp[d][i]; } d^=1;//^1 就是加1或者减1交替进行 } double ans=0; for(int i=l-1;i<r;i++) ans+=dp[d][i]; cout<<setiosflags(ios::fixed)<<setprecision(4)<<ans<<endl; } return 0; }
[ACM] HDU 4576 Robot (概率DP,滚动数组),布布扣,bubuko.com
[ACM] HDU 4576 Robot (概率DP,滚动数组)
原文:http://blog.csdn.net/sr_19930829/article/details/38338631