BZOJ[2428][HAOI2006]均分数据 模拟退火

33 篇文章 0 订阅
1 篇文章 0 订阅

传送门ber~

模拟退火骗分

每次随机一个点,然后把它随机放入另外一个集合里,如果解更优就更新,如果不是更优,则根据当前温度随机判断是否更新,温度越高更新的几率越高,并不断降温,直到小于精度为止

多做几遍即可

代码如下:

#include<algorithm>
#include<cstring>
#include<ctype.h>
#include<cstdio>
#include<cmath>
#define eps 1e-4
#define INF 2147483647
#define N 10020
using namespace std;
const int root=20020605;
inline int read(){
    int x=0,f=1;char c;
    do c=getchar(),f=c=='-'?-1:f; while(!isdigit(c));
    do x=(x<<3)+(x<<1)+c-'0',c=getchar(); while(isdigit(c));
    return x*f;
}
int n,m;
int a[N],belong[N],sum[N];
double ans=1e30,ave;
inline double SA(){
    double ans=0,T=10000;
    memset(sum,0,sizeof sum);
    for(int i=1;i<=n;i++){
        belong[i]=rand()%m+1;///每个数随机放到一个集合里
        sum[belong[i]]+=a[i];
    }
    for(int i=1;i<=m;i++)
        ans+=(sum[i]-ave)*(sum[i]-ave);///ans是当前的每组的和与平均数差的平方和
    while(T>eps){
        T*=0.9;///降温
        int t=rand()%n+1,x=belong[t],y=0;///t:要拿走的数x:从哪个集合拿走y:放到哪里
        if(T>1000){///如果温度太高,则说明数列不稳定,挑一个和比较小的集合把t放到那里
            for(int i=1;i<=m;i++)
                if(!y || sum[i]<sum[y])
                    y=i;
        }
        else y=rand()%m+1;///否则随机找一个集合放进去
        if(x==y) continue;
        double tmp=ans;
        tmp-=(sum[x]-ave)*(sum[x]-ave);tmp-=(sum[y]-ave)*(sum[y]-ave);
        sum[x]-=a[t];sum[y]+=a[t];
        tmp+=(sum[x]-ave)*(sum[x]-ave);tmp+=(sum[y]-ave)*(sum[y]-ave);
        if(tmp<=ans || rand()%10000<T)///如果解更优,或概率到那里的话就更新
            belong[t]=y,ans=tmp;
        else sum[x]+=a[t],sum[y]-=a[t];///否则不更新
    }
    return ans;
}
int main(){
    srand(root);
    n=read();m=read();
    for(int i=1;i<=n;i++){
        a[i]=read();
        ave+=a[i];
    }
    ave=ave/(double)m;
    for(int i=1;i<=10000;i++)///多做几遍,玄学东西
        ans=min(SA(),ans);
    printf("%.2lf",sqrt(ans/m));
return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值