热身赛C.饱和式救援(热身) 概率dp 0.42s

Description

“在全球性救援开始的0.42秒后,MOSS就已经推算出结果,这是一场注定徒劳的救援。”

在《流浪地球》电影中,虽说在引爆木星之后推动了地球离开木星,但是大爆炸摧毁了地球上大部分的行星发动机。

人类再一次展开全球性救援。此时的MOSS已经被烧毁,现在告诉你每只救援队的目标发动机的编号以及这只救援队在规定时间内成功救援的概率,假如有至少k个行星发动机能够得到重启,则认为地球会被拯救。请你设计一个程序,在0.42秒内帮助人类完成这个计算。

Input

第一行给出N,M,K。N代表人类派出的救援队总数,M代表被摧毁的行星发动机,K代表至少需要重启的行星发动机总数。(N<=1e5,K<=M<=2000)

接下来N行,每行给出ai,pi,分别代表第i支救援队的目标发动机的编号是ai,救援成功的概率为pi。(1<=ai<=M,0<=pi<=1)

只要有一只救援队顺利抵达该行星发动机,则认为该发动机被成功重启。

Output

输出地球被救援成功的概率(请严格保留3位小数)

3 2 2
1 1
1 1
2 0.5

0.500

k<=m 注意dp求和范围
1s 1e8 0.5s 5e7 0.42s 能跑4e6
2000*2000 二重循环 通liuxx泡妹子概率dp
k-m dp[2000][2000]假如2000个救援队 每个成功概率为1
至少k=1个重启
dp[2000][1]+dp[2000][2]…=2000

#include<iostream>
#include<vector>
#include<cstring>
#include<algorithm>
#include<cstdio> 
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int maxn=1e5+5;
const ll inf=0x3f3f3f3f3f3f3f3f;
double p[2005];
double dp[2005][2005];//2000个 发动机
struct node
{
	int hao;
	double pp;
	double sheng;
}a[maxn];
bool cmp(node a,node b)
{
	if(a.hao==b.hao)
		return a.pp>b.pp;
	return a.hao<b.hao;
}
int main()
{
	ios::sync_with_stdio(false);
	int n,m,k;
	cin>>n>>m>>k;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i].hao>>a[i].pp;
		a[i].sheng=1-a[i].pp;
	}
	sort(a+1,a+n+1,cmp);
	
	for(int i=1;i<=m;i++)
	{
		p[i]=1;
	}
	
	int cnt=1;
	for(int i=1;i<=n && cnt<=m;i++)	//1e5
	{
		while(a[i].hao!=cnt)
			cnt++;
		if(a[i].hao==cnt)
		{
			p[cnt]=p[cnt]*a[i].sheng;//所有救援队都不成功 
		}
	}
	
	
	for(int i=1;i<=m;i++)
	{
		p[i]=1-p[i];
	}
/*	for(int i=1;i<=m;i++)
	{
		cout<<p[i]<<endl;
	}*/
	dp[0][0]=1;
	for(int i=0;i<m;i++)
	{
		for(int j=0;j<=i;j++)
		{
			dp[i+1][j]+=dp[i][j]*(1-p[i+1]);//此发动机未能成功重启 
			dp[i+1][j+1]+=dp[i][j]*p[i+1];//此发动机能成功重启 
		}
	}
	double ans=0;
	for(int i=k;i<=m;i++)
	{
		ans+=dp[m][i];
	}
	printf("%.3f\n",ans);
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/qq_40423146/article/details/88669057
今日推荐