#P1587. 第3题-Never die fourth
-
1000ms
Tried: 53
Accepted: 13
Difficulty: 8
所属公司 :
百度
时间 :2023年9月19日
-
算法标签>动态规划
第3题-Never die fourth
思路:概率DP
首先,我们需要计算攻击每个怪物失败的概率。对于每个怪物,我们有四种可能的结果:成功,失败一次,失败两次,失败三次
然后,我们使用动态规划计算攻击所有怪物失败的概率。我们定义f[i][j]为攻击前i个怪物,失败次数为j的概率。对于第i个怪物,我们有四种可能的失败次数(0,1,2,3),我们需要将这四种情况的概率累加到f[i][j]中。
最后,我们计算攻击怪物的期望。对于每个失败次数i,我们将f[n][i]∗(i/3)累加到结果中。这是因为每失败三次,就会爆发一次小宇宙,所以失败次数i对应的小宇宙爆发次数为i/3。
代码
C++
#include<bits/stdc++.h>
using namespace std;
const int N=510;
double w[N],f[N][N*3],p[N][4];
int n;
int main(){
cin>>n;
for(int i=1;i<=n;i++)cin>>w[i];
for(int i=1;i<=n;i++){ //计算攻击每个怪物,失败次数为j的概率
p[i][0] = (1.0-w[i]);
p[i][1] = w[i]*p[i][0];
p[i][2] = w[i]*p[i][1];
p[i][3] = 1 - p[i][0] - p[i][1] - p[i][2];
}
f[0][0]=1.0;
for(int i=1;i<=n;i++){
for(int j=0;j<=i*3;j++){
for(int k=0;k<=3;k++){ //当前攻击这个怪物失败,失败的次数为k
f[i][j+k]+=f[i-1][j]*p[i][k]; //上一次攻击的怪物失败的次数为j-k
}
}
}
double res=0; //计算攻击怪物的期望
for(int i=0;i<=n*3;i++){
res+=f[n][i]*(i/3);
}
cout<<fixed<<setprecision(9)<<res<<endl;
return 0;
}
Java
import java.util.Scanner;
import java.text.DecimalFormat;
public class Main {
static final int N = 510;
static double[] w = new double[N];
static double[][] f = new double[N][N * 3];
static double[][] p = new double[N][4];
static int n;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
n = scanner.nextInt();
for (int i = 1; i <= n; i++) {
w[i] = scanner.nextDouble();
}
for (int i = 1; i <= n; i++) {
p[i][0] = (1 - w[i]);
p[i][1] = w[i] * p[i][0];
p[i][2] = w[i] * p[i][1];
p[i][3] = 1 - p[i][0] - p[i][1] - p[i][2];
}
f[0][0] = 1.0;
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= i * 3; j++) {
for (int k = 0; k <= 3; k++) {
f[i][j + k] += f[i - 1][j] * p[i][k];
}
}
}
double res = 0;
for (int i = 0; i <= n * 3; i++) {
res += f[n][i] * (i / 3);
}
System.out.println(res);
}
}
Python
n = int(input())
w = [0] + list(map(float, input().split()))
p = [[0]*4 for _ in range(n+1)]
f = [[0]*(n*3+1) for _ in range(n+1)]
for i in range(1, n+1):
p[i][0] = 1 - w[i]
p[i][1] = w[i] * p[i][0]
p[i][2] = w[i] * p[i][1]
p[i][3] = 1 - p[i][0] - p[i][1] - p[i][2]
f[0][0] = 1.0
for i in range(1, n+1):
for j in range(i*3+1):
for k in range(4):
if j + k <= i * 3:
f[i][j+k] += f[i-1][j] * p[i][k]
res = 0
for i in range(n*3+1):
res += f[n][i] * (i // 3)
print("{:.9f}".format(res))
题目描述
小红正在游玩一款魂类游戏。
这款游戏有n个BOSS,小红按BOSS编号从小到大的顺序挑战BOSS,挑战第i个BOSS时,有pi的概率失败,1−pi的概率成功。同时,当小红连续挑战一个BOSS失败三次时,下一次一定挑战成功。
小红每失败三次,就会爆发一次小宇宙。
小红想知道,当他挑战完所有的BOSS时,期望爆发多少次小宇宙?
输入描述
第一行一个整数n,代表BOSS的数量
第二行n个数字pi,表示小红挑战第i个BOSS的成功概率为pi,pi精确到小数点后5位。
1≤n≤500
0<pi≤1
输出描述
一个数字,代表期望爆发小宇宙的次数,要求精度误差不超过10−5
样例
输入
2
0.50000 0.50000
输出
0.328125