补题链接
可能产生最小花费Ex
的两种情况
.
一. 不使用hint
,此时需要将所有打开所有箱子,所以Ex
就是所有花费之和
.
二. 使用hint
,刚开始使用hint
,此时就知道所有的黑球的数量(cnt
),当打开一个箱子后,如果这个箱子里面是黑球
,则cnt--
,否则cnt
不变,如果当前cnt == 剩余的箱子数
,则剩下的箱子里面全
是黑球
,如果cnt == 0
,则剩下的箱子里面全
为白球
,当能根据打开的箱子确定剩下的箱子的球的颜色时
,则不需要打开剩余的箱子
,此时的花费为打开前m
个箱子所要的花费,此时的概率为(剩下的箱子全为同色
的概率 – 假如已经打开
了i
个箱子,此时的 p = 0.5 ^ n - i
,而此时的Exi = sum[i] * p
),而题目中要求min
的值,所以先对花费进行升序
排列(因为每个箱子概率完全一样且相互独立,如果先开小的开到某个箱子可以根据推出来的黑球的数量直接判断后面箱子里球的颜色就不用继续开了),总的Ex就是
sum[i] * (1 / 2) ^ (n - i)
代表打开前i
个箱子所用的花费与出现这种情况(后面的球颜色可以从当前打开的箱子的球的颜色确定)的概率的乘积(要出现此种情况,后面的球颜色必须相同),i
从 1 ~ n - 1
,因为当打开第n - 1
箱子时,就肯定可以确定第n
个箱子的球的颜色,所以此时不用花费额外的钱。
最后对一、二情况求个最小值即可。
using namespace std;
const int N = 1e5 + 10;
int n;
double ht, tol, res, w[N], sum[N];
int main(){
scanf("%d%lf", &n, &ht);
for(int i = 1; i <= n; i++){
scanf("%lf", &w[i]);
tol += w[i];
}
sort(w + 1, w + n + 1);
for(int i = 1; i <= n; i++){
sum[i] = sum[i - 1] + w[i];
}
res += ht;
for(int i = 1; i <= n - 1; i++){
res += sum[i] * pow(0.5, n - i);
}
tol = min(tol, res);
printf("%.7f", tol);
return 0;
}