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

 

posted on 2013-08-14 15:38  jumpingfrog0  阅读(645)  评论(0编辑  收藏  举报

导航