1. 程式人生 > >bzoj2428: [HAOI2006]均分數據

bzoj2428: [HAOI2006]均分數據

calc() sqrt div 貪心 pri ios 本機 就是 name

垃圾bzoj本機AC提交WA,精A

%你退火可解

因為n很小所以我們可以降溫慢點,為了更優我們先在開始的時候選擇一個數貪心地放到總和最小地那一組

然後就是不停換隨機種子T_T

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
double sqr(double x){return x*x;}
double drand(){return double(rand()%10000)/10000.0;} int n,m,p[30];double a[30],mmin; double sum[30]; double calc() { memset(sum,0,sizeof(sum)); for(int i=1;i<=n;i++)sum[p[i]]+=a[i]; double ave=0; for(int i=1;i<=m;i++)ave+=sum[i]; ave/=double(m); double ret=0
; for(int i=1;i<=m;i++)ret+=sqr(ave-sum[i]); ret=sqrt(ret/(double)m); if(ret<mmin)mmin=ret; return ret; } void annealing() { double T=1000000.0; while(T>1) { double k1=calc(); int pp=1; for(int i=1;i<=m;i++)
if(sum[i]<sum[pp])pp=i; int x=rand()%n+1,np; while(p[x]==pp){x++;if(x==n+1)x=1;} np=p[x],p[x]=pp; double k2=calc(); if(k1>k2||exp((k1-k2)/T)>drand()); else p[x]=np; T*=0.9997; } while(T>0.0001) { int x=rand()%n+1,pp=rand()%m+1,np; if(pp==p[x]){pp++;if(pp==m+1)pp=1;} double k1=calc(); np=p[x],p[x]=pp; double k2=calc(); if(k1>k2||exp((k1-k2)/T)>drand()); else p[x]=np; T*=0.9997; } for(int i=1;i<=1000;i++) { int x=rand()%n+1,pp=rand()%m+1,np; if(pp==p[x]){pp++;if(pp==m+1)pp=1;} double k1=calc(); np=p[x],p[x]=pp; double k2=calc(); p[x]=np; } } int main() { srand(25424); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%lf",&a[i]), p[i]=rand()%m+1; random_shuffle(a+1,a+n+1); mmin=calc(); annealing(); printf("%.2lf",mmin); return 0; }

bzoj2428: [HAOI2006]均分數據