某不知名的题 - 概率DP
2016-03-17 19:04
281 查看
两名玩家进行对战,P1拥有N点血量,P2用有M点血量。
两人均有一定概率可以打出1-6点上海,每次两名玩家进行对战的时候,伤害高的一方可以打掉伤害低的一方一点血量。
已知N,M以及两名玩家的攻击力概率。求P1是胜利的概率。
输入
多组输入,魅族输入两个整数N,M表示玩家的血量(1<=N,M<=2000)
随后输入两组浮点数每组6个浮点数,分别表示P1,P2打出1-6伤害的概率。
输出
对于每组输入输出P1的胜率(输入保留两位小数)
示例输入
5 5
1.00 0.00 0.00 0.00 0.00 0.00
0.00 0.00 0.00 0.00 0.00 1.00
示例输出
0.00
思路:我们用二维dp数组表示出p1的血量和p2的血量分别到达a和b的概率即dp[a][b],这是我们假设p1和p2赢的概率为wp1和wp2,现在有状态转移方程
dp[a][b]=dp[a-1][b]*wp2+dp[a][b-1]*wp1
但是我们没有考虑到平局的情况,假设平局概率为f对于dp[a-1][b]到达dp[a][b]可能直接p2赢也可能平一局,也或许平3局所以
dp[a][b]=dp[a-1][b]*(wp2+f*wp2+f^2*wp2+...+f^n*wp2)+dp[a][b-1]*(wp1+f*wp1+f^2*wp1+...+f^n*wp1)
提出wp2剩余一个等比数列,由前n项和且f^n趋近于0可得前n项和为1/(1-f)
dp[a][b]=dp[a-1][b]*wp2/(1-f)+dp[a][b-1]*wp1/(1-f)
以上就是状态转移方程
我们最后只需要将dp[i][m](0<=i<=n-1)相加得到最终答案
注意:dp不能直接递推到dp[i][m]当p2到达m状态时p1已经获胜,不能继续递推到下个状态。
两人均有一定概率可以打出1-6点上海,每次两名玩家进行对战的时候,伤害高的一方可以打掉伤害低的一方一点血量。
已知N,M以及两名玩家的攻击力概率。求P1是胜利的概率。
输入
多组输入,魅族输入两个整数N,M表示玩家的血量(1<=N,M<=2000)
随后输入两组浮点数每组6个浮点数,分别表示P1,P2打出1-6伤害的概率。
输出
对于每组输入输出P1的胜率(输入保留两位小数)
示例输入
5 5
1.00 0.00 0.00 0.00 0.00 0.00
0.00 0.00 0.00 0.00 0.00 1.00
示例输出
0.00
思路:我们用二维dp数组表示出p1的血量和p2的血量分别到达a和b的概率即dp[a][b],这是我们假设p1和p2赢的概率为wp1和wp2,现在有状态转移方程
dp[a][b]=dp[a-1][b]*wp2+dp[a][b-1]*wp1
但是我们没有考虑到平局的情况,假设平局概率为f对于dp[a-1][b]到达dp[a][b]可能直接p2赢也可能平一局,也或许平3局所以
dp[a][b]=dp[a-1][b]*(wp2+f*wp2+f^2*wp2+...+f^n*wp2)+dp[a][b-1]*(wp1+f*wp1+f^2*wp1+...+f^n*wp1)
提出wp2剩余一个等比数列,由前n项和且f^n趋近于0可得前n项和为1/(1-f)
dp[a][b]=dp[a-1][b]*wp2/(1-f)+dp[a][b-1]*wp1/(1-f)
以上就是状态转移方程
我们最后只需要将dp[i][m](0<=i<=n-1)相加得到最终答案
注意:dp不能直接递推到dp[i][m]当p2到达m状态时p1已经获胜,不能继续递推到下个状态。
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> using namespace std; double dp[2010][2010]; int main() { double p1[7],p2[7]; int n,m; while(~scanf("%d%d",&n,&m)) { double wp1=0,wp2=0,f12=0; for(int i=0;i<6;i++) { scanf("%lf",&p1[i]); } for(int i=0;i<6;i++) { scanf("%lf",&p2[i]); } for(int i=1;i<6;i++) { for(int j=0;j<i;j++) { wp1 += p1[i]*p2[j]; } } for(int i=1;i<6;i++) { for(int j=0;j<i;j++) { wp2 += p2[i]*p1[j]; } } for(int i=0;i<6;i++) { f12 += p1[i]*p2[i]; } wp1/=(1-f12); wp2/=(1-f12); dp[0][0]=1; for(int i=1;i<=n;i++) { dp[i][0]=(dp[i-1][0]*wp2); } for(int i=1;i<=m;i++) { dp[0][i]=(dp[0][i-1]*wp1); } for(int i=1;i<n;i++) { for(int j=1;j<m;j++) { dp[i][j]=(dp[i-1][j]*wp2+dp[i][j-1]*wp1); } } double ans=0; for(int i=0;i<n;i++) { ans += dp[i][m-1]*(wp1); } printf("%.2lf\n",ans); } return 0; }
相关文章推荐
- 插入排序
- Runtime
- 项目:DoubleFaceCamera
- Java List与数组之间的转换
- 工厂设计模式
- Spring-data连接MongoDB及Redis配置及druid连接mysql配置
- 由于log太多导致ubuntu硬盘空间满了,进入不了系统解决办法
- IOS 杂笔-4(属性与成员变量的区别)
- 内置系统用户
- 项目:BluetoothChat
- 《Linux内核与分析》第四周
- 土地测量
- linux下redis安装
- 系统运维和网络运维技能对比
- 40.iOS6与iOS7屏幕适配 edgesForExtendedLayout
- B-字符串
- HydroCMS水利设计管理系统,基于beego框架
- LeetCode Single Number I / II / III
- 支付宝支付
- 项目:简单记事本