AtCoder Beginner Contest 332 E题 Lucky bag

E题:Lucky bag

标签:贪心、随机化
题意:给你 n n n件物品,第 i i i件物品的权重为 w i w_i wi,想要把这些物品分成 d d d组,希望最小化总重量的方差。
方差定义: V = 1 D ∑ i = 1 D ( x i − x ˉ ) 2 V=\frac{1}{D}\displaystyle\sum_{i=1}^D (x_i-\bar{x})^2 V=D1i=1D(xixˉ)2 x ˉ \bar{x} xˉ定义为各组数据和的平局值: x ˉ = 1 D ( x 1 + x 2 + ⋯ + x D ) \bar{x}=\frac{1}{D}(x_1+x_2+\cdots+x_D) xˉ=D1(x1+x2++xD)
题解: 通过观察能发现这是一个贪心,当 x i x_i xi的值越接近答案越小, 我们可以把每个数加到当前和最小的组里,然后通过随机化 进行多次贪心,随机化的次数可以稍微多点。每次贪心把序列打乱, 然后多次进行操作获得对应的值,从中取最小值就可以了。
代码

#include <bits/stdc++.h>
using namespace std;

int n, d, w[20], b[20], t = 2000000;
double ans = 1e18, sum = 0;

int main() {
    cin >> n >> d;
    for (int i = 1; i <= n; i++) {
        cin >> w[i];
        sum += w[i];
    }
    double avg = sum / d;
    while (t--) {
        memset(b, 0, sizeof(b));
        random_shuffle(w + 1, w + n + 1);
        int k = 1;
        sum = 0;
        for (int j = 1; j <= n; j++) {
            for (int i = 2; i <= d; i++) {
                if (b[i] < b[k]) k = i;
            }
            b[k] += w[j];
            k = 1;
        }
        for (int i = 1; i <= d; i++) sum += (avg - b[i]) * (avg - b[i]);
        sum = sum / d;
        ans = min(ans, 1.0 * sum);
    }
    printf("%.15lf", ans);
    return 0;
}
  • 17
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值