随机退火算法

爬山算法

一种搜索算法,在某个状态的时候仅会向相邻更高的点走去,当周围没有更高的状态的时候,即认为它是最优解,其中对于高度实际上是一种估值,且有概率找不到最优的结果。

随机退火算法

是一种对于爬山算法的改进优化。具体的优化是即使当其周围没有更高的点,同样有一定的概率会去转移到更低的点,而这样一个概率是会随着时间不断减少的。
根据热力学的原理,在温度为T时,出现能量差为dE的降温的概率为P(dE),表示为:
		P(dE) = exp( dE/(kT) ) 
而随着程序的运行,接受的概率实际上是会越来越低的。
E=Val(ans); // Val为估值函数
while( T>T_min ){
	nE= Val( now );
	dE=nE-E; //dE 即是delta E 
	if(dE>0||eps(dE/T)>random(1,0)){  
		ans=next;
		E=nE; //改变当前状态的“能量” 
	}
	T=T*r;  // 0<r<1 r越大越有可能会找到最优解 

一道题目

POJ-1379

//#include<bits/stdc++.h>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <map>
#include <queue>
#include <iostream>
#include <algorithm>
#include <time.h>
#include <iomanip>

#define FOR(i,a,b) for(register int i=a;i<=b;i++)
#define LL long long
#define db double
#define Maxn 10000

using namespace std;

inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}

const db PI=acos(-1.0);
const int inf=0x7FFFFFFF;
int n;

struct Node{
	db x,y;
	Node(){ x=0; y=0; }
	Node(db a,db b){ x=a; y=b; }
}dot[Maxn+10];
db dis(Node a,Node b){ return sqrt( (db)(a.x-b.x)*(a.x-b.x)+(db)(a.y-b.y)*(a.y-b.y) ); }
db minDis(Node now){
	double ans=1e80;
	FOR(i,1,n) ans=min(ans,dis(now,dot[i]));
	return ans;
}
double random(){
	return rand()%10000/10000.0;
}
int X,Y;
Node Deal(){
	db T_min=1e-8; db T=sqrt( X*X+Y*Y )/2.0;
	Node Ans=Node(X/2.0,Y/2.0);
	db E=minDis(Ans); int count=30;
	while( T>T_min ){
		Node next;
		db nE=0.0;
		FOR(i,1,count){
			Node now;
			db angle=random()*2*PI;
			now=Node( Ans.x+T*cos(angle), Ans.y+T*sin(angle) );
			if(now.x>X) now.x=X; if(now.x<0.0) now.x=0.0;
			if(now.y>Y) now.y=Y; if(now.y<0.0) now.y=0.0;
			db tE=minDis(now);
			if(tE>nE) nE=tE, next=now;
		}
		db dE=nE-E;
		if(dE>=0.0|| exp(dE/T)>random() )
			E=nE, Ans=next;
		T=T*0.8;
	}
	return Ans;
}

int main(){
	
	srand((unsigned)time(0));
	//db l; while(1) if((l=random())>0.4) cout<<l<<endl;
	
	int T=read();
	FOR(i,1,T){
		
		X=read(), Y=read(), n=read();
		FOR(i,1,n) cin>>dot[i].x>>dot[i].y;
		Node Ans=Deal();
		//cout<<" A "<<Ans.x<<" "<<Ans.y<<endl;
		printf("The safest point is (%.1lf, %.1lf).\n",Ans.x,Ans.y);
	}

	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值