2021牛客多校5B Boxes (数学期望)

大意:给n个盒子,每个盒子里有一个有,为黑白的概率各为1/2,每打开一个盒子要花费w,或者获得一个提示,得知当前未开的盒子里黑球有多少,花费c,要求知道所有盒子中球的颜色的最低数学期望花费
开盒子有两种开法:
1:全开,花费为盒子权值之和
2:在游戏开始时获得提示,此后在一整局里都能知道接下来还有多少黑球(如果开出白球,剩余黑球数量不变,开出黑球,剩余黑球数量-1)
如果选择提示,有两种情况可以提前结束游戏:剩余黑球数量为0,或者剩余黑球数量等于当前剩余盒子数量
首先对盒子的权值排序,保证最先开盒子的是权值最小的。
如果一开局得到的提示为0个黑球或者全是黑球,那么可以直接结束游戏,这种情况的可能性是2*(1/2)^n,这个乘2是因为有全黑和全白两种情况 ,此时没开任何盒子,权值为0
在任意时刻,当黑球数量为0,或者黑球数量等于剩余盒子数量。假设此时已经开到了第i个盒子,表明此刻剩余未开盒子数量是同一种颜色。
这要特别说明:如果当我们打开第i个盒子才知道结果,说明后面的盒子的颜色必定与第i个盒子的颜色是不同的,假如第i个盒子颜色与后面盒子相同,那么我们在打开第i-1个盒子时,就已经知道答案了,所以后面盒子的颜色是被固定了的,在我们开第i个盒子知道答案的概率(剩余盒子全是与i不同色球的概率)是pow(0.5,n-i),不需要乘上2,其权值为(前i个盒子打开的花费*pow(0.5,n-i))。
最后再对两种开法取个最小值即可

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int n;
double c;
double w[N];
double s[N];

int main() {
    
    
	cin >> n >> c;
	for (int i = 1; i <= n; i++) {
    
    
		cin >> w[i];
	}
	//两种情况:1全部开一遍
	//2:开始提示一次,之后黑球数量就一直知道了
	sort(w + 1, w + 1 + n); //排序,优先开权值小的,更优
	for (int i = 1; i <= n; i++) {
    
    
		s[i] = w[i] + s[i - 1]; //前缀和,开启前i个盒子需要多少钱
	}

	double ans1 = s[n]; //第一种做法:全开
	double ans2 = c; //支付咨询费用
	for (int i = 1; i <= n - 1; i++) {
    
     //只需要开前n-1个即可,获取提示后最后一个是能直接知道的
		ans2 += s[i] * pow(0.5, n - i);
	}
	double ans=min(ans2,ans1);
	printf("%.7f",ans);
}





猜你喜欢

转载自blog.csdn.net/fdxgcw/article/details/119809683