【算法学习】模拟退火

P1337 吊打XXX

SA 无疑就这几个步骤。

  1. 设初温 t;

  2. 降低系数 down<1

  3. 设定阈值

  4. 更劣随机概率选择(温度越低,概率越低)

AI 评价:

image

#include<bits/stdc++.h>
using namespace std;
#define down 0.996 //降低系数 
int n;
struct node{
	int x,y,w;
}point[10006];

double ansx,ansy,answ;

double energy(double x,double y){
	double r=0,dx,dy;
	
	for(int i=1;i<=n;i++){//计算能量总和,总和越小越稳定 
		dx=x-point[i].x;
		dy=y-point[i].y;
		r+=sqrt(dx*dx+dy*dy)*point[i].w;
	}
	return r;
}

void sa(){
	double t=3000;//设置初温,是控制接受较差解的概率 
	while(t>1e-15){//设置温度阈值,当温度低于阈值时,停止降温过程
		double ex=ansx+(rand()*2-RAND_MAX)*t;//根据当前温度随机生成新的解 
		double ey=ansy+(rand()*2-RAND_MAX)*t; 
		double ew=energy(ex,ey);//计算新值 
		double de=ew-answ;//计算新值和旧值的差 
		if(de<0){//越小越稳定,更优 
			ansx=ex;
			ansy=ey;
			answ=ew;
		}
		else if(exp(-de/t)*RAND_MAX>rand()){//概率选择更劣的值,温度越小概率越小 
			ansx=ex;
			ansy=ey;
		}
		t*=down;//降低温度 
	}
}

int main(){
	ios::sync_with_stdio(false);
	cin>>n;
	
	for(int i=1;i<=n;i++){
		cin>>point[i].x>>point[i].y>>point[i].w;
		ansx+=point[i].x;//初始化 
		ansy+=point[i].y;
	}
	
	ansx/=n;//取平均值更合理 
	ansy/=n;
	answ=energy(ansx,ansy);//初始值 
	
	while ((double)clock()/CLOCKS_PER_SEC<0.975) sa();//卡时 
	
	printf("%.3lf %.3lf",ansx,ansy);
	
    return 0;
}
posted @ 2024-09-05 16:15  sad_lin  阅读(5)  评论(0编辑  收藏  举报