[HDU 4576]Robot[概率DP]

题意:

环形cell, robot初始在1号,顺逆时针走概率各半.每次走w,问x次后停在l和r之间的概率.

思路:

正着推,方程很显然. 需要注意空间优化为2行, 时间上减少mod的次数.

#include <cstdio>
#include <cstring>

using namespace std;

const int MAXM = 1e6+5;
const int MAXN = 205;

double dp[2][MAXN];
int m,n,l,r,w;

inline int mymod(int a, int mod)//[1,n]
{
    return ((a-1)%mod + mod)%mod + 1;
}


int main()
{
    while(scanf("%d %d %d %d",&n,&m,&l,&r) && (n+m+l+r))
    {
        memset(dp[0],0,sizeof(dp[0]));
        dp[0][1] = 1;
        for(int i=1;i<=m;i++)
        {
            scanf("%d",&w);
            for(int j=1;j<=n;j++)
            {
                if(j-w>=1)
                {
                    if(j+w<=n)
                        dp[i&1][j] = 0.5*dp[(i&1)^1][j-w] + 0.5*dp[(i&1)^1][j+w];
                    else
                        dp[i&1][j] = 0.5*dp[(i&1)^1][j-w] + 0.5*dp[(i&1)^1][mymod(j+w,n)];
                }
                else
                {
                    if(j+w<=n)
                        dp[i&1][j] = 0.5*dp[(i&1)^1][mymod(j-w,n)] + 0.5*dp[(i&1)^1][j+w];
                    else
                        dp[i&1][j] = 0.5*dp[(i&1)^1][mymod(j-w,n)] + 0.5*dp[(i&1)^1][mymod(j+w,n)];
                }
            }
        }
        double ans = 0;
        for(int i=l;i<=r;i++)
            ans += dp[m&1][i];
        printf("%.4lf\n",ans);
    }
}


你可能感兴趣的:([HDU 4576]Robot[概率DP])