BZOJ2428: [HAOI2006]均分数据 模拟退火

来源:互联网 发布:vnc mac 连windows 编辑:程序博客网 时间:2024/05/20 22:04

题意:N个数分成M组,要求均方差最小
N<=20,M<=6
随机一种分法,然后模拟退火,每次把一个数随机分到另外一组,若rand(0,1)< exp(dt/T)则判定为成功。然而WA了很久,最后知道温度高的时候需要贪心把它放入当前和最小的一组。。。还是不行,于是改成了从头模拟退火20次才终于过了,慢得垫底,真玄学

#include<cstdio>#include<cstdlib>#include<cmath>#include<cstring>using namespace std;int n,m;int w[20],a[20][21],t[20],sum[20],pos[20];inline double F(){    int asum=0;    for(int i=0;i<m;++i)    {        sum[i]=0;        for(int j=1;j<=t[i];++j)        sum[i]+=w[a[i][j]];        asum+=sum[i];    }    double dx=floor(asum)/m,res=0;    for(int i=0;i<m;++i)    res+=(sum[i]-dx)*(sum[i]-dx);    return res;}inline int move(int x,int p){    int b=pos[x];    for(int i=t[b]--;;--i)    {        if(a[b][i]==x)        {            for(;i<=t[b];++i)            a[b][i]=a[b][i+1];            break;        }    }    a[p][++t[pos[x]=p]]=x;    return b;}inline bool failed(const double &dt,const double &T){    return dt<0.0&&exp(dt/T)<=floor(rand())/RAND_MAX;}inline void random_shuffle(){    int aim;    for(int i=0;i<n;++i)    {        pos[i]=aim=rand()%m;        a[aim][++t[aim]]=i;    }}inline int greedy_choice(){    int minn=0x7fffffff,res;    for(int i=0;i<m;++i)    {        sum[i]=0;        for(int j=1;j<=t[i];++j)        sum[i]+=w[a[i][j]];        if(sum[i]<minn) minn=sum[i],res=i;    }    return res;}inline double fire(){    memset(t,0,sizeof t);    double T=1e16,ans,dt,res;    int ele,aim,org;    random_shuffle();    res=ans=F();    while(T>1e-10)    {        ele=rand()%n;        if(T>1e2) aim=greedy_choice();        else aim=rand()%m;        org=move(ele,aim);        dt=ans-F();        if(ans-dt<res) res=ans-dt;        if(failed(dt,T)) move(ele,org);        else ans-=dt;        T*=0.999;    }    return res;}inline void min(double &a,const double &b){    if(b<a) a=b;}int main(){    srand(114514);    scanf("%d%d",&n,&m);    for(int i=0;i<n;++i)    scanf("%d",w+i);    double ans=1e10;    for(int i=1;i<=20;++i)    min(ans,sqrt(fire()/m));    printf("%.2lf\n",ans);    return 0;}
0 0
原创粉丝点击