标签:
题意: A,B掷骰子,对于每一次点数大者胜,平为和,A先胜了m次A赢,B先胜了n次B赢。
WA了那么多次这题目数据是错的,两个人的血量弄错了,输入的 A的血量其实是B的,输入B的其实是A的,由于有平局现象的干扰,所以一开始先把平局包括进去 的 A赢的概率B赢的概率都算出来,然后减去以后就是平局的概率(这个地方要特别注意一下,因为dp记录的是赢了几次那么乘以概率的时候只有输赢不能算进去平局),再在已经除去平局的情况里 算一下A赢的概率,B赢得概率计算出来,这样就可以计算了,
假设方程dp[i][j]代表 A赢了j次B赢了i次的概率,然后状态转移就比较简单了 :
dp[i][j] += dp[i][j - 1] * a_win;
dp[i][j] += dp[i - 1][j] * b_win;
然后就是需要注意的是 B至多赢n-1次,而A必须恰好赢m次,
一开始没注意,当A已经赢了以后第二个状态转移已经不需要再加了,一开始没注意,第二个状态转移多加了一次
还有这破题目,数组要是开dp[2050][2050]就会MLE....必须差不多刚好2005 * 2005
5 5 1.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 1.000 5 5 0.000 0.000 0.000 0.000 0.000 1.000 1.000 0.000 0.000 0.000 0.000 0.000
0.000000 1.000000
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> using namespace std; double dp[2000 + 5][2000 + 5]; int main() { int n,m; double a[7],b[7]; double a_win,b_win; while(~scanf("%d %d",&n,&m)) { for(int i=0; i<6; i++) scanf("%lf",&a[i]); for(int i=0; i<6; i++) scanf("%lf",&b[i]); a_win=0; b_win=0; for(int i=1; i<6; i++) for(int j=0; j<i; j++) a_win+=a[i]*b[j]; for(int i=1; i<6; i++) for(int j=0; j<i; j++) b_win+=b[i]*a[j]; double p=a_win+b_win; a_win/=p; b_win/=p; memset(dp,0,sizeof(dp)); dp[0][0]=1; for(int j=0; j<n; j++) for(int i=0; i<m; i++) { if(i+j>0) { if(i>0) dp[i][j]+=dp[i-1][j]*b_win; if(j>0) dp[i][j]+=dp[i][j-1]*a_win; } } double ans=0; for(int i=0; i<m; i++)//这个地方因为有两个条件导致的第一个是当A赢了n次那么就停止了,如果上面是<=n那么就会有重复,所以用n-1最后再乘以一次赢得概率就行了 ans+=dp[i][n-1]*a_win; if (ans>1) ans=1; printf("%.6lf\n",ans); } return 0; }
标签:
原文地址:http://blog.csdn.net/wweiainn/article/details/43914329