HDUOJ 4576 2013杭州邀请赛重现 Robot

本文介绍了一种通过迭代计算在环形路径上特定区域出现概率的方法。利用动态规划思想,结合时间换空间技巧,有效解决了内存限制问题。

传送门

题意:有一个长度为n的环,起始在1位置,m代表走的次数,下接m行,分别是每次步数,但是不知道是顺时针还是逆时针,最后问在 l 和 r 之间的概率。

思路:根据前一次在每个点的概率,推出下一次在每个点的概率,复杂度O(mn),最坏情况2亿次计算,4s想想差不多够用。第0次(即最开始)在1的概率是1,在其他位置的概率是0,这里用p[0][1]=1表示第0次在1的概率为1。拿第二组样列来举例子吧:第一次可以走1步,那么它可以从1走到2或5,然后p[1][2]+=p[0][1]/2,p[1][5]+=p[0][1]/2,这样第一次走完,就只可能在2和5啦,概率分别为1/2和1/2。然后考虑第二次,第二次走2步,从2走可能到4和5,于是p[2][4]+=p[1][2]/2,p[2][5]+=p[1][2]/2;从5走可以走到2或3,p[2][2]+=p[1][5]/2,p[2][3]+=p[1][5]/2。这步走完后,分别可以出现在2,3,4,5,概率分别为1/4,1/4,1/4,1/4。然后出现在4~4的概率自然就是1/4啦。

然而这不是现场赛,内存不是你想开多大就开多大的,按照上面思路要开至少p[1000000][200]大的float数组,我MLE了几次,之后就用滚动数组,即开p[2][200],每次前一步是p[0][x],计算下一步p[1][x],之后再将p[1][x]赋给p[0][x]做下一次计算。这里差不多就是时间换空间啦。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
float p[2][201],ans;
int m,n,l,r,a,ra,la;
int main()
{
    while(scanf("%d%d%d%d",&n,&m,&l,&r))
    {
        if(n==0&&m==0&&l==0&&r==0)return 0;
        memset(p,0,sizeof(p));
        p[0][1]=1;
        for(int i=1;i<=m;i++)
        {
            scanf("%d",&a);
            for(int j=1;j<=n;j++)
            {
                if(p[0][j]==0)continue;
                la=j-a;
                while(la<=0)la+=n;
                ra=j+a;
                while(ra>n)ra-=n;
                p[1][la]+=p[0][j]/2;
                p[1][ra]+=p[0][j]/2;
            }
            for(int i=1;i<=n;i++)
            {
                p[0][i]=p[1][i];
                p[1][i]=0;
            }
        }
        ans=0;
        for(int i=l;i<=r;i++)ans+=p[0][i];
        printf("%.4f\n",ans);
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值