问题描述:
小明想要在王者荣耀游戏里晋升一个段位,假设他一共需打了n场比赛,且必须成功赢得至少70%的场次才能成功晋升。假设每场比赛小明获胜的概率分别=3为p1,p2,…,pn,请帮他算出成功晋级段位的概率是多少?
输入:
参数1:整数num(0<= num <=1000),表示比赛的场数。
参数2:整数数组p[num] = {p1,p2,…,pnum},其中pi表示小明有pi%的概率赢得第i场比赛。(0 <=pi <= 100)
输出:
成功晋级段位的概率,保留小数点后5位,最后结果四舍五入。
分析
这个问题可以看作:
先求解小明进行i场比赛并且赢了j场的概率
然后再求i=num,j>=num0.7(num0.7向上取整)时的结果
运用我们刚刚学的DP四步骤:
关于DP四步骤可以看动态规划(Dynamic Programming)入门
确定状态
- 最后一步:在进行了i场比赛后赢了j场
- 子问题:当第i场输了的时候,那么在前i-1场比赛,共赢了j场;当第i场赢了的时候,那么在前i-1场比赛,共赢了j-1场.
状态:设f[i][j]表示在进行了i场比赛后赢了j场的概率
转移方程
这里要分两种情况:
当j=0时,f[i][j]=f[i-1][0]*(1-p[i])
当j>0时,f[i][j]=f[i-1][j]*(1-p[i])+f[i-1][j-1]p[i]
初始条件和边界情况
初始条件:
f[0][0]=1、f[k][k]=p1*p2…pk
计算顺序
DP的目的是利用历史记录,不重复计算,所以,我们先枚举j的情况,再枚举i的情况。
代码实现:
package algorithm;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class DPSolution {
public static double probability(int[] p,int num) {
double pass=0.0d;//晋级的概率