首页 > 代码库 > hdu4405:概率dp
hdu4405:概率dp
题意:
总共有n+1个格子:0-n
初始情况下在 0号格子 每次通过掷骰子确定前进的格子数
此外 还有一些传送门可以瞬间从 u 点传送到 v 点(必须被传送)
求走到(或超过)n点总共需要掷多少次骰子
分析:
太弱 只想到了n^2的 dp方程 可惜n是100000...纠结半天又看了大牛的题解
用 dp[i]记录 走到第 i 个点时的期望 p[i]记录第 i 个点的概率。。、
这个概率记录的感觉比较神奇 ,我先开始想到的n^2是记录用 i 步 走到 j 点的概率
题解的这个概率应该是??平均后的???f反正就是走到这个点了的概率直接把步数省去了 dp方程就少了一维
dp[i]=次数 * p 那么 如果对于 i+j 点 dp[i+j]= (次数+1)*p*1/6 = ( dp[i]+p[i] ) / 6;
就可以写出转移方程了
同时在维护一个next数组记录 传送门 如果next[i]!=i 则证明不可能停在第 i 点 因此就不通过此点进行转移 直接continue,并把 i 的信息保存在next[i]中
统计答案的时候注意要统计 n到 n+5的和
ac代码:
#include <iostream>#include <stdio.h>#include<string.h>#include<algorithm>#include<string>#include<ctype.h>using namespace std;#define MAXN 10000int n,m;int next[100010];double dp[100010];double p[100010];void ini(){ memset(dp,0,sizeof(dp)); memset(p,0,sizeof(p)); for(int i=0;i<=100000;i++) { next[i]=i; } int u,v; for(int i=0;i<m;i++) { scanf("%d%d",&u,&v); next[u]=v; }}void solve(){ dp[0]=0; p[0]=1; for(int i=0;i<n;i++) { if(next[i]!=i) { p[next[i]]+=p[i]; dp[next[i]]+=dp[i]; p[i]=0; continue; } for(int j=1;j<=6;j++) { p[i+j]+=p[i]*1.0/6.0; dp[i+j]+=(dp[i]+p[i])*1.0/6.0; } } double ans=0; for(int i=n;i<n+6;i++) { ans+=dp[i]; } printf("%.4f\n",ans);}int main(){ while(scanf("%d%d",&n,&m),m+n) { ini(); solve(); } return 0;}
hdu4405:概率dp
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。