玄关,P2503 [HAOI2006] 均分数据 模拟退火求调
  • 板块学术版
  • 楼主zhengzidu
  • 当前回复1
  • 已保存回复1
  • 发布时间2023/12/19 21:00
  • 上次更新2023/12/20 10:55:13
查看原帖
玄关,P2503 [HAOI2006] 均分数据 模拟退火求调
954640
zhengzidu楼主2023/12/19 21:00
#include<bits/stdc++.h>
#define dacty main 
using namespace std;
inline long long read(){
	long long x=0;
	short f=1;
	char c=getchar();
	while(c>57||c<48){
		if(c==45) f=-1;
		c=getchar();
	}
	while(c<58&&c>47){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x*f;
}
inline void write(long long x){
	if(x<0ll) putchar(45),x=~x+1;
	if(x>9ll) write(x/10);
	putchar(x%10|48);
}
int n,m;
int group[45];
int data[45];
double sum[45],ave,ans=1e15;
double temperature=3000.000;
double delta=0.9912;
double last_temp=1e-10;
double change;
int pos;
double cal(double sum[],double omega){
	double calculate=0.000;
	for(int i=1;i<=m;i++){
		calculate+=((sum[i]-ave)*(sum[i]-ave));
	}
	return calculate;
}
void Simulate_Anneal(){
	memset(sum,0,sizeof(sum));
	for(int i=1;i<=n;i++){
		group[i]=rand()%m+1;
		sum[group[i]]+=data[i];
	}
	for(double temp=temperature;temp>last_temp;temp*=delta){
		double fewest=0x3f3f3f3f3f3f3f3f;
		for(int i=1;i<=m;i++){
			if(sum[i]<fewest){
				fewest=sum[i];
				pos=i;
			}
		}
		int x=rand()%n+1;
		change=cal(sum,ave);
		double now=change;
		change=change-(sum[group[x]]-ave)*(sum[group[x]]-ave)+(sum[pos]-ave)*(sum[pos]-ave);
		sum[group[x]]-=data[x];
		sum[pos]+=x;
		change=change+(sum[group[x]]-ave)*(sum[group[x]]-ave)+(sum[pos]-ave)*(sum[pos]-ave);
		if((change<now)||(exp((change-now)/temp)<rand()/RAND_MAX)) group[x]=pos;
		else{
			change=now;
			sum[group[x]]+=data[x];
			sum[pos]-=data[x];
		}
	}
	if(change<ans) ans=change;
}
signed dacty(){
	srand(time(0));
	n=read();
	m=read();
	for(int i=1;i<=n;i++){
		data[i]=read();
		ave+=data[i];
	}
	ave/=m;
	for(int i=1;i<=6000;i++) Simulate_Anneal();
	printf("%.2lf",sqrt(ans/m));
	return 0;
}

T=T= 3000.0003000.000

退火系数 =0.9912=0.9912

末温度 =1e−15=1e-15

跑 60006000 次

蒟蒻想问一下为何此代码无法 ACAC

2023/12/19 21:00
加载中...