BZOJ2428:[HAOI2006]均分数据
我对模拟退火的理解:https://www.cnblogs.com/AKMer/p/9580982.html
题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=2428
遗传算法和爬山算法在\(OJ\)上\(A\)题的可能性太小了,还是退火好,可以对我在\(BZOJ\)的账号做一点贡献。
对于这道题,我们首先得明白状态空间是啥。
这道题要求一个最优的分组方法,使得每一组的权值和的方差最小,那么状态就是\(n\)个数分别放在哪一个组里。
然后我们就可以用一个长度为\(n\)的数组来记录状态,寻找邻居节点的时候随机一个数字,将它放到另一组去就是一个新状态了。然后对于方差最小这个要求,我们可以灵性的贪心一波,比如每次都把这个数字移到权值和最小的那一组去。这样在很大几率上会直接减少方差。
每个状态对应的权值就是该状态分配下的方差。
然后退个六七十遍火就是了。
时间复杂度:\(O(能A)\)
空间复杂度:\(O(能A)\)
代码如下:
#include <cmath>
#include <ctime>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define sqr(a) ((a)*(a))
const int maxn=30;
const double T_0=1e-7,del_T=0.998;
int n,m;//n个数字,m组
double ave,ans;//ave存平均值,ans存历史最小方差
int a[maxn],d[maxn],b[maxn],c[maxn],e[maxn];//a存数字,b[i]存第i个数字当前在第几组,d[i]存第i个数字在历史最优状态下在第几组,c[i]存第i组当前权值,e[i]存第i组在历史最优状态下的权值
int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
}//快读
double calc(int pos,int group) {//计算把pos号数字放到第group组后的方差
double sum=0;
for(int i=1;i<=m;i++) {
double tmp=c[i]-ave;
if(tmp==b[pos])tmp-=a[pos];
if(tmp==group)tmp+=a[pos];
sum+=sqr(tmp);//按照数学公式计算
}
return sqrt(sum/m);//记得返回double,不然会被卡精度
}
void Anneal() {
memcpy(b,d,sizeof(d));
memcpy(c,e,sizeof(e));//每次都从最优状态开始
double T=1e7;//初始温度1e7,结束温度1e-7,del_T为0.998;
while(T>=T_0) {
int group=0,mn=1e9;
for(int i=1;i<=m;i++)
if(c[i]<mn)mn=c[i],group=i;//找最小的那一组编号
int pos=rand()%n+1;
double tmp=calc(pos,group);//计算新状态的答案
if(tmp<ans) {//如果新状态更优
c[b[pos]]-=a[pos];c[group]+=a[pos];
b[pos]=group;ans=tmp;
memcpy(d,b,sizeof(b));
memcpy(e,c,sizeof(c));//直接更新当前状态以及历史最优状态
}
else if(exp((ans-tmp)/T)*RAND_MAX>rand()) {//如果在一定的概率内
c[b[pos]]-=a[pos];c[group]+=a[pos];
b[pos]=group;//直接更新当前状态
}
T*=del_T;//降温
}
}
int main() {
srand(time(0));
n=read();m=read();
for(int i=1;i<=n;i++) {
a[i]=read();
b[i]=d[i]=rand()%m+1;
e[d[i]]+=a[i];
c[d[i]]+=a[i];ave+=a[i];
}ave/=m;ans=calc(0,0);//初始化一个状态
for(int i=1;i<=60;i++)
Anneal();//做60遍退火(好像这个代码稍微少一点点就A不了了)
printf("%.2lf\n",ans);//输出答案
return 0;
}
这题也可以用爬山写,和这个代码差不多,大家灵性脑补一波就好。
BZOJ2428:[HAOI2006]均分数据的更多相关文章
- bzoj2428: [HAOI2006]均分数据
模拟退火.挺好理解的.然后res打成了ans一直WA一直WA...!!!一定要注意嗷嗷嗷一定要注意嗷嗷嗷一定要注意嗷嗷嗷. 然后我就一直卡一直卡...发现最少1800次的时候就可以出解了.然后我就去调 ...
- bzoj2428 [HAOI2006]均分数据 模拟退火
[HAOI2006]均分数据 Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 3434 Solved: 1091[Submit][Status][Dis ...
- BZOJ2428[HAOI2006]均分数据——模拟退火
题目描述 已知N个正整数:A1.A2.…….An .今要将它们分成M组,使得各组数据的数值和最平均,即各组的均方差最小.均方差公式如下: ,其中σ为均方差,是各组数据和的平均值,xi为第i组数据的数值 ...
- BZOJ2428 HAOI2006均分数据(模拟退火)
显然可以状压dp.显然过不了. 考虑暴力模拟退火.每次随机改变一个数所属集合即可. 并不明白要怎么调参. #include<iostream> #include<cstdio> ...
- 【BZOJ2428】均分数据(模拟退火)
[BZOJ2428]均分数据(模拟退火) 题面 BZOJ 题解 先说说黄学长的做法: 当温度比较高的时候,贪心 每次随机一个数,把他放进当前和最少的那一组里面 温度足够低的时候就完全随机然后转移 这样 ...
- P2503 [HAOI2006]均分数据
P2503 [HAOI2006]均分数据 模拟退火+dp (不得不说,我今天欧气爆棚) 随机出1个数列,然后跑一遍dp统计 #include<iostream> #include<c ...
- bzoj 2428: [HAOI2006]均分数据 随机化
2428: [HAOI2006]均分数据 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/ ...
- 洛谷 P2503 [HAOI2006]均分数据 随机化贪心
洛谷P2503 [HAOI2006]均分数据(随机化贪心) 现在来看这个题就是水题,但模拟赛时想了1个小时贪心,推了一堆结论,最后发现贪心做 不了, 又想了半个小时dp 发现dp好像也做不了,在随机化 ...
- 【BZOJ2428】[HAOI2006]均分数据
Description 已知N个正整数:A1.A2.…….An .今要将它们分成M组,使得各组数据的数值和最平均,即各组的均方差最小.均方差公式如下: ,其中σ为均方差,是各组数据和的平均值,xi为第 ...
- BZOJ2428:[HAOI2006]均分数据——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=2428 https://www.luogu.org/problemnew/show/P2503 已知 ...
随机推荐
- EasyDSS流媒体服务器软件对数据库Sqlite3和MySQL的同时支持说明
EasyDSS流媒体音视频直播与点播服务器软件,是一套提供一站式的转码.点播.直播.检索.回放.录像下载服务的高性能RTMP/HLS/HTTP-FLV流媒体服务,极大地简化了流媒体相关业务的开发和集成 ...
- office2013安装/激活
ed2k://|file|cn_office_professional_plus_2013_x64_dvd_1134006.iso|914106368|E5FBAE9EE9CB35D5E777EA78 ...
- 转载一篇将C/C++ 与lua混合使用入门讲的比较好的文章
转自 http://www.open-open.com/home/space-6246-do-blog-id-1426.html Lua是一个嵌入式的脚本语言,它不仅可以单独使用还能与其它语言混合调用 ...
- 洛谷 2216 [HAOI2007]理想的正方形
题目戳这里 一句话题意 给你一个a×b的矩形,求一个n×n的子矩阵,矩阵里面的最大值和最小值之差最小. Solution 这个题目许多大佬都是单调队列,但是我不是很会,只好用了比较傻逼的方法: 首先我 ...
- centos修改mysql密码或者进入mysql后解决Access denied for user ''@'localhost' to database 'mysql错误
原因是MySQL的密码有问题 用mysql匿名用户可以进入数据库,但是看不见mysql数据库. 解决办法:具体操作步骤:关闭mysql:# service mysqld stop然后:# mysqld ...
- Java实现时间日期格式转换示例
package com.hanqi.util; import java.text.ParseException; import java.text.SimpleDateFormat; import j ...
- SVG嵌入HTML
将SVG图像嵌入到HTML文件有多种方法: 使用<iframe>元素来嵌入SVG图像 使用<img>元素来嵌入SVG图像 将SVG图像作为背景图像嵌入 直接使用<svg& ...
- 转 Oracle 11g服务详细介绍
转自http://www.cnblogs.com/userWuLiang/archive/2013/04/13/3017900.html Oracle 11g服务详细介绍及哪些服务是必须开启的? 成功 ...
- 常用grads函数
GrADS的函数分两类, 一类是对格点/站点数据执行运算的,这一类我们姑且称之为分析函数; 另一类是脚本编程(gs)时使用的, 这后一类我们姑且称之为脚本函数. 第一类分析函数又分为格点分析和站点分析 ...
- 算法(Algorithms)第4版 练习 1.5.2
0 1 2 3 4 5 6 7 8 9 10 components 9 0 0 1 2 3 4 5 6 7 8 9 components 3 4 0 1 2 4 5 6 7 8 0 8 compone ...