我对模拟退火的理解: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]均分数据的更多相关文章

  1. bzoj2428: [HAOI2006]均分数据

    模拟退火.挺好理解的.然后res打成了ans一直WA一直WA...!!!一定要注意嗷嗷嗷一定要注意嗷嗷嗷一定要注意嗷嗷嗷. 然后我就一直卡一直卡...发现最少1800次的时候就可以出解了.然后我就去调 ...

  2. bzoj2428 [HAOI2006]均分数据 模拟退火

    [HAOI2006]均分数据 Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 3434  Solved: 1091[Submit][Status][Dis ...

  3. BZOJ2428[HAOI2006]均分数据——模拟退火

    题目描述 已知N个正整数:A1.A2.…….An .今要将它们分成M组,使得各组数据的数值和最平均,即各组的均方差最小.均方差公式如下: ,其中σ为均方差,是各组数据和的平均值,xi为第i组数据的数值 ...

  4. BZOJ2428 HAOI2006均分数据(模拟退火)

    显然可以状压dp.显然过不了. 考虑暴力模拟退火.每次随机改变一个数所属集合即可. 并不明白要怎么调参. #include<iostream> #include<cstdio> ...

  5. 【BZOJ2428】均分数据(模拟退火)

    [BZOJ2428]均分数据(模拟退火) 题面 BZOJ 题解 先说说黄学长的做法: 当温度比较高的时候,贪心 每次随机一个数,把他放进当前和最少的那一组里面 温度足够低的时候就完全随机然后转移 这样 ...

  6. P2503 [HAOI2006]均分数据

    P2503 [HAOI2006]均分数据 模拟退火+dp (不得不说,我今天欧气爆棚) 随机出1个数列,然后跑一遍dp统计 #include<iostream> #include<c ...

  7. bzoj 2428: [HAOI2006]均分数据 随机化

    2428: [HAOI2006]均分数据 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/ ...

  8. 洛谷 P2503 [HAOI2006]均分数据 随机化贪心

    洛谷P2503 [HAOI2006]均分数据(随机化贪心) 现在来看这个题就是水题,但模拟赛时想了1个小时贪心,推了一堆结论,最后发现贪心做 不了, 又想了半个小时dp 发现dp好像也做不了,在随机化 ...

  9. 【BZOJ2428】[HAOI2006]均分数据

    Description 已知N个正整数:A1.A2.…….An .今要将它们分成M组,使得各组数据的数值和最平均,即各组的均方差最小.均方差公式如下: ,其中σ为均方差,是各组数据和的平均值,xi为第 ...

  10. BZOJ2428:[HAOI2006]均分数据——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=2428 https://www.luogu.org/problemnew/show/P2503 已知 ...

随机推荐

  1. MySql存储过程及MySql常用流程控制语法

    /* 该代码是创建了一个名叫"p4"的存储过程并设置了s1,s2,s3两个int型一个varchar型参数,还可以是其他数据类型,内部创建了x1,x2两个变量 DELIMITER是 ...

  2. android菜鸟学习笔记24----与服务器端交互(一)使用HttpURLConnection和HttpClient请求服务端数据

    主要是基于HTTP协议与服务端进行交互. 涉及到的类和接口有:URL.HttpURLConnection.HttpClient等 URL: 使用一个String类型的url构造一个URL对象,如: U ...

  3. 3.设计模式----TemplateMethod模式

    模板模式,其实是一种思想,在开发中有很多地方用到模板,因为毕竟我们不可能每一个都一出一段!一个模板,填充不同,出来效果也是不一样! 准备画个时序图的,没找到工具,过几天补上! 模板模式在出现bug时候 ...

  4. Linux根目录下重要文件夹

    bin存放系统命令的目录,普通用户和超级用户都可以执行,不过放在这里的命令在单用户模式下也可以执行 sbin保存和系统环境设置相关的命令,只有超级用户可以使用这些命令进行系统环境的设置,但有些命令可以 ...

  5. git clone了整个远程仓库分支

    git之远程标签下载(远程分支) 一般我们发布一个新版本到线上服务器时都会在版本库中打一个标签,这样我们可以随时查看这个打标签的版本,就是说标签其实是版本库中一个快照.git的标签与分支类似,区别是分 ...

  6. perl智能匹配

    1.perl中~~为智能匹配,它能够智能地依据符号两側的操作数来确定操作. 如要推断某个元素是否存在于数组中,不使用智能匹配,程序像这样: my $x=2; my @array=(1,2,3); my ...

  7. linux系统环境下搭建coreseek(+mmseg3) (good)

    1.下载并解压coreseek软件,操作命令如下: wget http://www.coreseek.cn/uploads/csft/3.2/coreseek-3.2.14.tar.gz 说明:文件下 ...

  8. Microsoft Office Document Imaging批量ocr 方法

    先将pdf文件->导出->tiff文件,生成pdf每页的tiff文件 使用 G:\SoftWare-new\tiff文件合并拆分工具 将一个导出的单个tiff合并为一个tiff文件 再用 ...

  9. 【三】MongoDB文档的CURD操作

    一.插入文档 使用insert方法插入文档到一个集合中,如果集合不存在创建集合,有以下几种方法: db.collection.insertOne({}):(v3.2 new)  #插入一个文档到集合中 ...

  10. shell正则

    第五天 REGEXP:REGular EXPressionPattern: 正则表达式: Basic REGEXP:基本 Extended REGEXP:扩展 基本正则表达式: 字符匹配类:.: 任意 ...