我对模拟退火的理解: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. Gone Fishing(贪心)

    Gone Fishing John is going on a fising trip. He has h hours available (1 ≤ h ≤ 16), and there are n ...

  2. ASP连接数据库SQLServer

    Set conn=Server.CreateObject("adodb.connection")Set conn1=Server.CreateObject("adodb. ...

  3. Asp.Net 5 Web Hook

    首先,然我们来看一下WebHooks是什么.WebHooks是一个协议.它们是HTTP回调技术.并且它们是"用户定义的HTTP回调".你和 (或) 您的应用程序在有什么事情发生时会 ...

  4. spring属性注入方式

    一.使用有参构造注入属性 配置文件 constructor-arg标签是需注入属性的名字 User类 生成了User的有参构造函数 测试类 结果 打印出了name属性的值 二.使用set方法注入属性 ...

  5. 教你使用SQL查询(1-12)

    教你使用 Select 查询语句 (1) SELECT 语句基本语法简介 http://jimshu.blog.51cto.com/3171847/1363101(2) TOP 和 OFFSET 筛选 ...

  6. matlab 调用 python

    众所周知,Python凭借其众多的第三方模块,近年来被数据分析.机器学习.深度学习等爱好者所喜爱,最主要的是Python还是开源的.另一方面,MATLAB因其在仿真方面的独特优势也被众多人追捧.而在国 ...

  7. IOS UI Frame 相对位置调整 与优化方法 Height Width X Y 调整

    不使用xib ,纯代码开发的过程中,动态UI  需要改对象的大小位置 反复使用CGRectMake 去 setFrame  非常低效耗时,而且 牵一发动全身. 以下整理出几个方法,方便动态布局 1.s ...

  8. uCGUI 按键窗口切换机制(更新篇)

    在之前文章中,讲述了一个低内存使用量的的窗口切换机制.有人会问,低内存使用量是多低呢,我这里举个例子.我有一个项目中使用到本切换机制,128*64的单色屏,初步计算有105个窗口(后面还会增加),总内 ...

  9. 全屏滚动插件之 fullpage.js

    前言:做移动端网页下滑/点击切换到下一页的效果,采用了fullpage,js最新的版本 https://cdnjs.cloudflare.com/ajax/libs/fullPage.js/3.0.4 ...

  10. 常用阻止ajax缓存方法集锦

    HTML 通过添加meta标签 <meta http-equiv= "pragma" content= "no-cache"/> (pragma: ...