hdu4576(概率DP)
题意:一个圆盘,有N个编号(1,2,3……N),从1号出发,每次能逆时针或顺时针向前走w步,问经过m次后,最终停留在区间【l,r】的概率。
思路:只要先求出经过m次后,最终在每个点的概率,然后把区间里的概率全部加起来即可。dp[i][j]表示第j次后停留在i的概率,那么这个状态显然是由两个状态递推过来的。dp[i][j]=dp[(i+w+n)%n][j-1]*0.5+dp[(i-w+n)%n][j-1]*0.5,发现每次转移只是第j和第j-1之间的转移所以第二维可以开滚动数组dp[i][temp]=0.5*dp[(i+w+n)%n][temp^1]+0.5*dp[(i-w+n)%n][temp^1];最后的ans直接就是:for(int i=l-1;i<=r-1;i++) ans+=dp[i][temp];具体代码如下:
#include <stdio.h> #include <string.h> #include <algorithm> #include <cstring> double dp[205][2]; int main() { int n,m,l,r; while(scanf("%d%d%d%d",&n,&m,&l,&r)!=EOF) { if(n+m+l+r==0)break; memset(dp,0,sizeof(dp)); dp[0][0]=1; int temp=0; while(m--){ int w; scanf("%d",&w); temp^=1; for(int i=0;i<n;i++){ dp[i][temp]=0.5*dp[(i+w+n)%n][temp^1]+0.5*dp[(i-w+n)%n][temp^1]; } } double ans=0; for(int i=l-1;i<=r-1;i++){ ans+=dp[i][temp]; } printf("%.4lf\n",ans); }; return 0; }
主要体会一下求概率DP和求期望DP的区别,发现概率一般是正推过来的,而期望一般是逆推的。(比如本题和2013山东省赛那道期望DP)