BZOJ 2428 JZYZOJ1533 : [HAOI2006]均分数据 模拟退火 随机化

http://www.lydsy.com/JudgeOnline/problem.php?id=2428

http://172.20.6.3/Problem_Show.asp?id=1533

http://blog.csdn.net/qpswwww/article/details/44161053

本来用了看的博客里的srand想缩短时间不知道为什么wa了,在本校oj也挂了一组,但是不管是挂的数据在本地测,还是成组数据在本地测都是ac的。问了学长然后去掉了srand提高了次数,ac了。应该就是srand的锅,因为在bzoj上不去掉srand提高次数也是wa。

 1 /**************************************************************
 2     Problem: 2428
 3     User: 137shoebills
 4     Language: C++
 5     Result: Accepted
 6     Time:4884 ms
 7     Memory:1304 kb
 8 ****************************************************************/
 9  
10 #include<iostream>
11 #include<cstdio>
12 #include<cstring>
13 #include<algorithm>
14 #include<cmath>
15 using namespace std;
16 const int maxn=30;
17 int n,m;
18 int a[maxn]={};
19 int org[maxn]={};
20 int sum[maxn]={};
21 double xa=0,ans=100000;
22 void doit(){
23     memset(sum,0,sizeof(sum));
24     for(int i=1;i<=n;i++){
25         org[i]=rand()%m+1;
26         sum[org[i]]+=a[i];
27     }
28     double cnt=0,lcnt,T=10000;
29     for(int j=1;j<=m;j++){
30         cnt+=((double)sum[j]-xa)*((double)sum[j]-xa);
31     }cnt/=(double)m;
32     while(T>0.1){//温度设定
33         T*=0.9;
34         int x=rand()%n+1,y,mi=10000;//随机选一个数,最小和对应位置,最小和
35         if(T>500)//温度高贪心温度低随机
36             for(int i=1;i<=m;i++){if(mi>sum[i]){mi=sum[i];y=i;}}
37         else y=rand()%m+1;
38         if(y==org[x]){continue;}
39          
40         sum[org[x]]-=a[x];sum[y]+=a[x];
41         lcnt=cnt;cnt=0;//重新算方差
42         for(int j=1;j<=m;j++){
43             cnt+=((double)sum[j]-xa)*((double)sum[j]-xa);
44         }cnt/=(double)m;
45          
46         if(cnt<lcnt)org[x]=y;
47         else if(rand()%10000>T)org[x]=y,cnt=lcnt;
48         else{
49             sum[org[x]]+=a[x];sum[y]-=a[x];
50         }
51         if(cnt<ans)ans=cnt;//更新答案
52     }
53 }
54 int main(){
55     //freopen("data.in","r",stdin);
56     //freopen("data.out","w",stdout);
57     scanf("%d%d",&n,&m);
58     //srand(20010123);
59     for(int i=1;i<=n;i++){
60         scanf("%d",&a[i]);xa+=a[i];
61     }xa/=(double)m;
62     for(int i=1;i<=40000;i++)doit();
63     printf("%.2f
",sqrt(ans));
64     return 0;
65 }
View Code

原文地址:https://www.cnblogs.com/137shoebills/p/8470399.html