链接:https://ac.nowcoder.com/acm/contest/892/B
来源:牛客网
题目:饱和式救援
“在全球性救援开始的0.42秒后,MOSS就已经推算出结果,这是一场注定徒劳的救援。”
在《流浪地球》电影中,虽说在引爆木星之后推动了地球离开木星,但是大爆炸摧毁了地球上大部分的行星发动机。
人类再一次展开全球性救援。此时的MOSS已经被烧毁,现在告诉你每只救援队的目标发动机的编号以及这只救援队在规定时间内成功救援的概率,假如有至少k个行星发动机能够得到重启,则认为地球会被拯救。请你设计一个程序,帮助人类完成这个计算。
输入描述:
第一行给出N,M,K。N代表人类派出的救援队总数,M代表被摧毁的行星发动机,K代表至少需要重启的行星发动机总数。(1<=N<=1e5,K<=M<=2000)
接下来N行,每行给出ai,pi,分别代表第i支救援队的目标发动机的编号是ai,救援成功的概率为pi。(1<=ai<=M,0<=pi<=1)
只要有一只救援队顺利抵达该行星发动机,则认为该发动机被成功重启。
输出描述:
输出地球被救援成功的概率(请严格保留3位小数)
输入
3 2 2
1 1
1 1
2 0.5
输出
0.500
首先求出每一台发动机修好的概率, 然后用dp求出m台发动机修好k台以上的概率, dp[i][j]表示前i台发动机修好j台的概率
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<string>
#include<vector>
#include<stack>
using namespace std;
double dp[2005][20005];
typedef long long ll;
double a[2005];
int n, m, k;
int main()
{
scanf("%d %d %d", &n, &m, &k);
fill(a + 1, a + m + 1, 1);
for (int i = 0; i < n; i++)
{
int q;
double p;
scanf("%d%lf", &q, &p);
a[q] *= (1.0 - p);
}
for (int i = 1; i <= m; i++)
a[i] = (1.0 - a[i]);//截止此处,为求出i发动机修好的概率a[i]
dp[1][1] = a[1];
dp[1][0] = 1.0 - a[1];
//给初始条件
for (int i = 2; i <= m; i++)
{
dp[i][0] = dp[i - 1][0] * (1.0 - a[i]);//需要给出dp[i][0], 递推用的到
for (int j = 1; j <= i; j++)
dp[i][j] = dp[i - 1][j] * (1.0 - a[i]) + dp[i - 1][j - 1] * a[i];
}
double ans = 0;
for (int i = k; i <= m; i++)
ans += dp[m][i];
printf("%.3lf\n", ans);
}