jzoj 3072 掷骰子 (概率dp)
来源:互联网 发布:如何卸载mac上的软件 编辑:程序博客网 时间:2024/05/17 06:05
Description
太郎和一只免子正在玩一个掷骰子游戏。有一个有N个格子的长条棋盘,太郎和兔子轮流掷一个有M面的骰子,骰子M面分别是1到M的数字.且掷到任意一面的概率是相同的.掷到几.就往前走几步.当谁走到第N格时,谁就获胜了。游戏中还有一个规则“反弹”.就是当一位选手要走到第N格外时.他就会后退(就像飞行棋进营一样)。
假设现在一位追手在A格.当他掷出B时:1.A+B<N,走到第A+B格,2.A+B=N,走到第N格,获胜。3.A+B≥N,走到第(N-(A+B-N)格现在太郎和兔子分别在第x和y格.接下来是太郎掷骰子,太郎想知道他赢得比赛的概率就多少。
100%的数据.10≤n≤ 2000,1≤m,x,y≤n-1
题解:概率dp
f[i][j] 表示太郎到达i,兔子到达j,太郎为先手,胜利的概率。
我们不妨从后往前dp
显然f[n][j]=1,f[i][n]=0;
那么f[n][n]呢,因为太郎是先手所以此时该太郎走,那么上一步就是兔子走的,所以上上步太郎到达的n,所以太郎必胜,f[n][n]=1;
对于剩下的情况,我们考虑分类讨论:
1。 i+m<=n,j+m<=n
对于这种情况我可以各自跳跃一步,走到后面已经推过的格子中直接累加后面所有胜利的概率,除以总的方案数即可。之所以可以这么推是因为这一步不会产生新的胜利状态。
2。i>n-m,j>n-m
进入到[n-m+1,n]这一段,就意味着进入了一种循环状态,我们跳过了又会跳回来,有可能无限的循环下去。
观察上面式子中的每一项,发现是一个公比为(1-1/m)^2 的等比数列,那么我们套用等比数列的求和公式
s+∞=a1/(1-p) p为公比,a1为序列的第一项。
3. i>n-m,j<=n-m
i可能有1/m的概率直接到达终点,同时如果在兔子没走这一步之前太郎就胜利了,那么推到当前步也一定是可以胜利的,是所以是(m-1)是因为新的胜利的状态我们已经单独考虑了。那么如果兔子也可以在当前步到达终点,是否需要考虑呢?不需要因为太郎是先手,我们只要在当前步到达终点,就胜利了。
4. i<=n-m,j>n-m
只有在i=n-m是太郎才能一步到达终点,考虑f[i+(1..m)][j]这是太郎为先手的胜利状态,所以在到达当前步之前我们要保证兔子走的那一步不能到达终点,所以是(m-1)
暴力dp是O(N^4),我们可以利用后缀矩阵优化将复杂度降为O(N^2)
#include<iostream>#include<cstdio>#include<algorithm>#include<cmath>#include<cstring>#define N 2003using namespace std;double m,f[N][N];int n,x,y;double sum(int x,int y,int x1,int y1){double t=f[x][y]-f[x1][y]-f[x][y1]+f[x1][y1];//cout<<t<<endl;return t;}int main(){ freopen("dice.in","r",stdin); freopen("dice.out","w",stdout); scanf("%d%lf%d%d",&n,&m,&x,&y); for (int i=n;i>=1;i--) for (int j=n;j>=1;j--){f[i][j]=f[i+1][j]+f[i][j+1]-f[i+1][j+1];if (i==n){f[i][j]++;continue;} if (j==n) continue; if (i+m>n&&j+m>n) f[i][j]+=1.0*m/(2.0*m-1.0); if (i+m<=n&&j+m<=n) f[i][j]+=(1.0/(m*m))*sum(i+1,j+1,i+m+1,j+m+1); if (i>n-m&&j<=n-m) f[i][j]+=((m-1)/(m*m))*sum(i,j+1,i+1,j+m+1)+1.0/m; if (i<=n-m&&j>n-m) f[i][j]+=((m-1)/(m*m))*sum(i+1,j,i+1+m,j+1)+(i==n-m)/(m*m);} /*for (int i=1;i<=n;i++) { for (int j=1;j<=n;j++) cout<<f[i][j]<<" "; cout<<endl; }*/ printf("%0.6lf\n",sum(x,y,x+1,y+1));}
- jzoj 3072 掷骰子 (概率dp)
- 【JZOJ 3072】 掷骰子
- 【JZOJ 3072】掷骰子
- 概率dp题,掷骰子
- JZOJ【3072】【NOIP2012模拟10.31】掷骰子
- 九度OJ 1255:骰子点数概率 (递归、DP)
- DP--划分问题(掷骰子)
- 【NOIP 模拟题】掷骰子(dp)
- 掷骰子,求得每个数的概率
- 【JZOJ 3082】骰子游戏
- 【JZOJ 3082】 骰子游戏
- 扔骰子,求概率
- 阿里 骰子概率问题
- 骰子点数的概率
- 等概率投骰子
- 题目1255:骰子点数概率(动态规划)
- poj3071(概率DP)
- codeforces148D(概率DP)
- struts2笔记
- CSAPP笔记:第一章 计算机系统漫游
- Visual Stdio C++ 编译器 编译 (GSL) GNU Scientific Library 的方法介绍(5)
- Python3创建虚拟环境
- hibernate笔记
- jzoj 3072 掷骰子 (概率dp)
- 面试45:圆圈最后剩下的数字(约瑟夫环)
- vue数组操作
- ImageView的重要属性
- DELPHI写的截图小工具源码(部分)
- Morris.js的参数说明和使用方法介绍
- win7上将webrtc源码生成all.sln
- 面向对象
- UVAlive-4643 Twenty Questions