hdu 4576 (简单dp+滚动数组)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4576

题意:给出1~n的环,m个操作,每次能顺时针或逆时针走w步,询问最后在l~r这段区间内概率。
(1<=n<=200) ,(0<=m<=1,000,000),(1<=l<=r<=n).
分析:每次从某一个数字到达另外数字的概率为0.5,按概率dp求出到达每个数字的概率,然后枚举从l到r的概率相加即可。
dp[i][j]表示第i次操作落在数字j上的概率,但是不能直接开1000000*200的数组来保存中间结果,这肯定是会爆掉的。
因为每次只需要取上一次的数据,所以可以用滚动数组,开dp[2][200]就行了
注意:w可能比n大,所以要先w%n
这一题卡时限卡的非常紧,代码稍微写挫一点就会超时了。
代码如下:

 1 #include<stdio.h>

 2 #include<string.h>

 3 double dp[2][210];

 4 int main()

 5 {

 6     int n,m,l,r,i,t,k,w;

 7     while(scanf("%d%d%d%d",&n,&m,&l,&r)!=EOF)

 8     {

 9         if(n==0&&m==0&&l==0&&r==0)

10             break;

11         memset(dp,0,sizeof(dp));

12         dp[0][0]=1;

13         t=0;

14         while(m--)

15         {

16             scanf("%d",&w);

17             w%=n;

18             k=t^1;

19             for(i=0;i<n;i++)

20                 dp[k][i]=0;

21             for(i=0;i<n;i++)

22             {

23                 if(!dp[t][i])   //时限卡的很紧,加这一句来优化,减少运算次数

24                     continue;

25                 dp[k][(i+w)%n]+=0.5*dp[t][i];

26                 dp[k][(i-w+n)%n]+=0.5*dp[t][i];

27             }

28             t=k;

29         }

30         double ans=0;

31         for(i=l;i<=r;i++)

32             ans+=dp[t][i-1];

33         printf("%.4lf\n",ans);

34     }

35     return 0;

36 }
View Code

 

你可能感兴趣的:(HDU)