bzoj 2428: [HAOI2006]均分数据

本文探讨了模拟退火算法在编程竞赛中的应用,通过实例代码展示了如何使用该算法解决实际问题,包括随机生成参数、优化过程以及算法性能评估。文中详细解释了算法原理、关键步骤和优化技巧,旨在帮助编程爱好者提高解决问题的能力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

模拟退火;

#include<bits/stdc++.h>
#define rep(i,k,n) for(int i=k;i<=n;i++)
using namespace std;
double ave=0.0,ans=0.0,tmp=0.0,T=10000.0,minans=1e30;
int n,m,sum[30],belong[30],a[30];
void fire(){T=10000.0;
memset(sum,0,sizeof(sum));
ans=0.0;
    for(int i=0;i<n;i++){int xx=rand()%m;sum[xx]+=a[i];belong[i]=xx;}
    for(int i=0;i<m;i++){ans+=(sum[i]*1.0-ave)*(sum[i]*1.0-ave);}
    while(T>0.1){
        T*=0.9;
        int t=rand()%n,y;int x=belong[t];
        if(T>500)
            y=min_element(sum,sum+m)-sum;
        else y=rand()%m;
        if(x==y)continue;
        tmp=ans;
        ans-=(sum[x]*1.0-ave)*(sum[x]*1.0-ave);
        ans-=(sum[y]*1.0-ave)*(sum[y]*1.0-ave);
        sum[x]-=a[t];sum[y]+=a[t];
        ans+=(sum[x]*1.0-ave)*(sum[x]*1.0-ave);
        ans+=(sum[y]*1.0-ave)*(sum[y]*1.0-ave);
        if(ans<=tmp)
            belong[t]=y;
            else if(rand()%10000>T){
                sum[x]+=a[t];sum[y]-=a[t];
                ans=tmp;
            }
            else belong[t]=y;
        minans=min(minans,ans); 
    }
}
int main(){
    //freopen("in.in","r",stdin);
    srand('L'+'T'+'Q');
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++){scanf("%d",&a[i]);ave+=(a[i]*1.0);
    }ave/=(double)m;
    rep(i,1,10000)
    fire();
    printf("%.2lf",sqrt(minans/m));
}

很神奇也很好玩的算法,我也就在bzoj上玩了20几遍罢了…尝试各种参数…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值