2428: [HAOI2006]均分数据

本文介绍了一种使用模拟退火算法解决将n个正整数分成m组,并最小化各组均方差的问题。通过随机重排元素并评估不同配置下的目标函数值来寻找最优解。

题目链接

题目大意:把 n 个正整数分成 m 组,最小化各组的均方差

题解:模拟退火2333

我的收获:2333

#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;
typedef double lf;
const int N = 25;

int n, m;
lf mid, ans;
int a[N], p[N];

inline lf sqr(lf x) {
    return x * x;
}

inline lf work() {
    int cnt = 1, sum = 0, i;
    lf tmp = 0, t1, t2;
    for (i = 1; i <= n && cnt < m; ++i)
        if (sum + a[p[i]] >= mid) {
            t1 = sqr(sum - mid), t2 = sqr(sum + a[p[i]] - mid);
            if (t1 < t2) tmp += t1, sum = a[p[i]];
            else tmp += t2, sum = 0;
            ++cnt;
        } else sum += a[p[i]];
    while (i <= n) sum += a[p[i++]];
    tmp += sqr(sum - mid);
    return tmp;
}

int main() {
    int i;
    scanf("%d%d", &n, &m);
    for (i = 1; i <= n; ++i) {
        p[i] = i;
        scanf("%d", a + i);
        mid += a[i];
    }
    mid /= m, ans = 1e60;
    for (i = 1; i <= 500000; ++i) {
        random_shuffle(p + 1, p + n + 1);
        ans = min(ans, work());
    }
    printf("%.2lf\n", sqrt(ans / m));
    return 0;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值