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 }
posted on 2013-08-14 15:38 jumpingfrog0 阅读(645) 评论(0) 编辑 收藏 举报