bzoj2428 [ HAOI2006 ] -- 模拟退火

题目大意:

已知N个正整数:A1、A2、……、An 。今要将它们分成M组,使得各组数据的数值和最平均,即各组的均方差最小。

思路:

考虑模拟退火。每次先对每个数随机分在哪个组,然后每次退火随机一个数x,将其换到组y,取y时按温度分类:

若温度高,则此时不稳定,y取温度最小的组。

若温度低,则此时已经接近稳定,随机选一个y。

只做一次显然有很大概率错误,所以要做至少1000次。

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<cstdlib>
 6 using namespace std;
 7 #define N 30
 8 #define M 20000
 9 double T,Ans=1000000000,Now,N2,A;
10 int i,j,k,x,y,X,Y,n,m,a[N],b[N],Sum[N];
11 inline int Getmin(){
12     int Ans=1;
13     for(int i=2;i<=Ans;i++)
14     if(Sum[i]<Sum[Ans])Ans=i;
15     return Ans;
16 }
17 inline double Calc(){
18     double Res=0;
19     for(int i=1;i<=m;i++)Res+=(Sum[i]-A)*(Sum[i]-A);
20     if(Res<Ans)Ans=Res;
21     return Res;
22 }
23 inline void SA(){
24     memset(Sum,0,sizeof(Sum));
25     for(int i=1;i<=n;i++)b[i]=rand()%m+1,Sum[b[i]]+=a[i];
26     T=10000;Now=Calc();
27     while(T>0.1){
28         x=rand()%n+1;
29         if(T>500)y=Getmin();else y=rand()%m+1;
30         if(b[x]==y){T*=0.9;continue;}
31         Sum[y]+=a[x];Sum[b[x]]-=a[x];N2=Calc();
32         if(N2<Now||rand()%10000<T)b[x]=y,Now=N2;else Sum[y]-=a[x],Sum[b[x]]+=a[x];
33         T*=0.9;
34     }
35 }
36 int main()
37 {
38     srand(123456789);
39     scanf("%d%d",&n,&m);
40     for(i=1;i<=n;i++)scanf("%d",&a[i]),A+=a[i];
41     A/=(double)m;
42     for(i=1;i<M;i++)SA();
43     printf("%.2lf",sqrt(Ans/(double)m));
44     return 0;
45 }

bzoj2428

时间: 2024-11-05 12:25:27

bzoj2428 [ HAOI2006 ] -- 模拟退火的相关文章

BZOJ2428 [HAOI2006]均分数据

正确方法是模拟退火? 根据wulala的讲法,我们多random_shuffle几发,对序列贪心一下就好了 反正都是随机化的做法,能过就行2333 1 /************************************************************** 2 Problem: 2428 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:3356 ms 7 Memory:816 kb 8 ***********

[HAOI2006][BZOJ2428] 均分数据

2428: [HAOI2006]均分数据 Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 801  Solved: 231[Submit][Status][Discuss] Description 已知N个正整数:A1.A2.…….An .今要将它们分成M组,使得各组数据的数值和最平均,即各组的均方差最小.均方差公式如下: ,其中σ为均方差,是各组数据和的平均值,xi为第i组数据的数值和. Input 第一行是两个整数,表示N,M的值(N是整数个数,

洛谷P2503 [HAOI2006]均分数据(模拟退火)

题目描述 已知N个正整数:A1.A2.…….An .今要将它们分成M组,使得各组数据的数值和最平均,即各组的均方差最小.均方差公式如下: 输入输出格式 输入格式: 输入文件data.in包括: 第一行是两个整数,表示N,M的值(N是整数个数,M是要分成的组数) 第二行有N个整数,表示A1.A2.…….An.整数的范围是1--50. (同一行的整数间用空格分开) 输出格式: 输出文件data.out包括一行,这一行只包含一个数,表示最小均方差的值(保留小数点后两位数字). 输入输出样例 输入样例#

[模拟退火] HAOI2006 均分数据

题目描述 已知N个正整数:A1.A2.--.An .今要将它们分成M组,使得各组数据的数值和最平均,即各组的均方差最小.均方差公式如下: 输入输出格式 输入格式: 输入文件data.in包括: 第一行是两个整数,表示N,M的值(N是整数个数,M是要分成的组数) 第二行有N个整数,表示A1.A2.--.An.整数的范围是1--50. (同一行的整数间用空格分开) 输出格式: 输出文件data.out包括一行,这一行只包含一个数,表示最小均方差的值(保留小数点后两位数字). 输入输出样例 输入样例#

COGS 307 模拟退火

307. [HAOI2006] 均分数据 ★★   输入文件:data.in   输出文件:data.out   简单对比时间限制:3 s   内存限制:128 MB [问题描述] 已知N个正整数:A1,A2,--,An.今要将它们分成M组,使得各组数据的数值和最平均,即各组的均方差最小.均方差公式如下:   其中第一个公式是均方差,第二个公式是各组数据和的平均值,xi为第i组数据的数值和. [输入格式]     第一行是两个整数,表示N,M的值(N是整数个数,M是要分成的组数).    第二行

BZOJ2428 均分数据

2428: [HAOI2006]均分数据 Time Limit: 5 Sec  Memory Limit: 128 MB Description 已知N个正整数:A1.A2.…….An .今要将它们分成M组,使得各组数据的数值和最平均,即各组的均方差最小.均方差公式如下: ,其中σ为均方差,是各组数据和的平均值,xi为第i组数据的数值和. Input 第一行是两个整数,表示N,M的值(N是整数个数,M是要分成的组数) 第二行有N个整数,表示A1.A2.…….An.整数的范围是1--50. (同一

模拟退火简述

模拟退火 本文提到的某些概念仅是个人的理解,并不意味着严格或主流的定义 算法简述 模拟退火是经典的乱搞搜索之一,用来找出系统的较优甚至最优状态,其主要思想是给予系统一定的"初始温度",逐渐"降温",直到降至"合适温度",在此过程中用随机化的方法使系统找到一个合适的状态. 模拟退火源自于物理上的退火,举两个例子: 1.在炼钢时,需要将高温的钢材冷却至常温,也就是退火,但是退火不能过快,否则会导致钢材品质下降,而如果慢慢退火,则能得到优质钢材,这是因

poj-2420 A Star not a Tree?(模拟退火算法)

题目链接: A Star not a Tree? Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5219   Accepted: 2491 Description Luke wants to upgrade his home computer network from 10mbs to 100mbs. His existing network uses 10base2 (coaxial) cables that allo

bzoj1051【HAOI2006】受欢迎的牛

1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 3491  Solved: 1837 [Submit][Status][Discuss] Description 每一头牛的愿望就是变成一头最受欢迎的牛.现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎. 这种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎.你的任务是求出有多少头牛被所有的牛认为是受欢迎的. I