2021牛客暑期多校训练营5

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×(12ni1)

两者取较小值即可。

代码

/*
 * @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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值