B.Boxes
题意
有n个盒子,每个盒子里可能是黑色或白色的球,且概率均为 1 2 \frac{1}{2} 21,现在可以询问没翻过的盒子里的黑球数,需要代价为C,翻每个盒子需要代价为 w i w_i wi,求最小的代价知道所有盒子里的球的颜色
思路
首先 C 最多只用花一次,且可以在最开始花,所以有两种策略:
直接全部打开,代价:
Σ
w
i
Σw_i
Σwi
将
w
i
w_i
wi升序排序。先花 C 的代价,剩下的就相当于一个随机 01 序列从前往后开,开到一个后缀全是同色的为止。代价:
C
+
Σ
w
i
×
(
1
−
1
2
n
−
i
)
C + Σ w_i\times (1-\frac{1}{2^n-i})
C+Σwi×(1−2n−i1)
两者取较小值即可。
代码
/*
* @Author: Icey_dying
* @Date: 2021-07-31 14:23:27
* @LastEditors: Icey_dying
* @LastEditTime: 2021-08-05 21:06:37
* @FilePath: \Icey_dying\competition\2021\2021.07\2021.07.31\B.cpp
*/
#include <bits/stdc++.h>
using namespace std;
int n;
double C,w[100005],sum,ans,tmp=1;
int main()
{
cin>>n>>C;
for(int i=1;i<=n;i++){
cin>>w[i];
sum+=w[i];
}
sort(w+1,w+1+n);
for(int i=n;i>=1;i--){
ans+=w[i]*(1-tmp);
tmp/=2;
}
printf("%.7f\n",min(sum,ans+C));
cout<<min(sum,ans+C)<<endl;
return 0;
}
J. Jewels
题意
有n个宝石,位置分别在 ( x i , y i , z i + t × v i ) (x_i,y_i,z_i+t\times v_i) (xi,yi,zi+t×vi),其中t为时间,想要打捞上来所需的代价为该宝石与原点的距离。
思路
首先一点,所有的宝石肯定都在 0 ~ n-1 这 n 个时刻被挖掉,那么问题就变成一个最小权匹配了,一边是时刻,一边是宝石,边权就是在这个时刻挖这个宝石所消耗的体力值。
代码
/*
* @Author: Icey_dying
* @Date: 2021-07-31 14:44:26
* @LastEditors: Icey_dying
* @LastEditTime: 2021-08-05 20:12:06
* @FilePath: \Icey_dying\competition\2021\2021.07\2021.07.31\J.cpp
*/
#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll n,ans=0;
struct sa{
ll z,v,no;
}a[305];
ll f(ll t,sa x){
t--;
return t*t*x.v*x.v+2*t*x.v*x.z;//增加的边权
}
void solve(int x){
int t;
for(int i=1;i<=n;i++)
if(a[i].no==x){
t=i;
break;
}
for(int i=1;i<=n;i++){
if(f(i,a[i])+f(t,a[t])>f(t,a[i])+f(i,a[t])){//找增广链
swap(a[i],a[t]);
solve(a[t].no);
solve(x);
}
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++){
ll x,y,z,v;
cin>>x>>y>>z>>v;
ans+=1ll*x*x+1ll*y*y+1ll*z*z;
a[i]={z,v,i};
}
for(int i=1;i<=n;i++) solve(i);
for(int i=1;i<=n;i++) ans+=f(i,a[i]);
cout<<ans<<endl;
return 0;
}