模拟退火 hdu3932

一.模拟退火算法的原理
模拟退火算法是一种元启发式(Meta-Heuristics)算法,来源于固体退火原理,将固体加热至充分高的温度,再让其徐徐冷却。加热时,固体内部粒子随温升变为无序状,内能增大,而徐徐冷却时粒子渐趋有序,在每个温度都达到平衡态,最后在常温时达到基态,内能减为最小。根据Metropolis准则,粒子在温度T时趋于平衡的概率为e-ΔE/kt,其中E为温度T时的内能,ΔE为其改变量,k为Boltzmann常数。
二.模拟退火算法的模型
① 初始化:初始温度T(充分大),初始解状态S(算法迭代的起点), 每次迭代次数L
② for k=1 to L 做③至⑥
③ 产生新解S’
④ 计算增量Δt′=C(S′)-C(S),其中C(S)为评价函数
⑤ 若Δt′<0则接受S’作为新的当前解,否则以概率e-Δt/k接受S’作为新的当前解
⑥ 如果满足终止条件则输出当前解作为最优解,结束程序

⑦ T逐渐减少,然后转②


//hdu 3932,求点的最小距离的最大值
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<ctime>
#include<cstdlib>
using namespace std;

#define PI 3.14159265358
#define LL long long 
#define MAXN 1005


const double eps = 1e-3;
const double INF = 1e20;

int max(int a, int b)
{
	if (a > b) return a;
	return b;
}

class Point
{
public:
	Point()
	{
		maxDis = -1;
	}
	Point(double tx, double ty)
	{
		x = tx;
		y = ty;
		maxDis = -1;
	}

	double x, y, maxDis;
};

double dis(Point a, Point b)
{
	return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));
}

Point hole[MAXN], fp[MAXN];

int X, Y, N, L, P;
double delta;

int main()
{
	//	Point a(0, 0), b(3, 4);
	//	cout << dis(a, b);
	//	cout<<"- -"<<endl;
	
	while (cin >> X >> Y >> N)
	{
		L = 25, P = 15, delta = double(max(X, Y)) / (sqrt(1.0*N));
		srand((unsigned int)time(NULL));
		for (int i = 0; i <= N - 1; i++)
		{
			cin >> hole[i].x >> hole[i].y;
		}
		for (int i = 0; i <= P - 1; i++)
		{
			//			cout << "- -" << endl;
			fp[i].x = double(rand() % 1000 + 1) / 1000 * X;
			fp[i].y = double(rand() % 1000 + 1) / 1000 * Y;
			fp[i].maxDis = -1;
			for (int j = 0; j <= N - 1; j++)
			{
				double tp = dis(fp[i], hole[j]);
				if (fp[i].maxDis < tp) fp[i].maxDis = tp;//找最大距离,用-1
			}
		}

		while (delta>eps)
		{
			for (int i = 0; i <= P - 1; i++)
			{
				//			Point tmp = fp[i];
				for (int k = 1; k <= L; k++)
				{
					double alpha = double(rand() % 1000 + 1) / 1000.0 * 2 * PI;
					Point tp;
					tp.x = fp[i].x + cos(alpha)*delta;
					tp.y = fp[i].y + sin(alpha)*delta;
					if (tp.x<0 || tp.x>X || tp.y<0 || tp.y>Y) continue;
					tp.maxDis = -1;
					for (int j = 0; j <= N - 1; j++)
					{
						double distp = dis(tp, hole[j]);
						if (tp.maxDis < distp) tp.maxDis = distp;
					}
					//					if (tp.x>=300||tp.y>=300)
					//					printf("##---(%.1lf,%.1lf)---%.1lf\n", tp.x, tp.y, tp.maxDis);
					if (tp.maxDis < fp[i].maxDis)
					{
						fp[i].maxDis = tp.maxDis;
						fp[i].x = tp.x;
						fp[i].y = tp.y;
					}
				}
			}

			delta *= 0.8;
		}


		int index = 0;
		for (int i = 0; i <= P - 1; i++)
		{
			//		printf("---(%.1lf,%.1lf)---%.1lf\n", fp[i].x, fp[i].y, fp[i].maxDis);
			if (fp[index].maxDis > fp[i].maxDis) index = i;
		}
			printf("(%.1lf,%.1lf).\n%.1lf\n", fp[index].x, fp[index].y, fp[index].maxDis);
		//printf("The safest point is (%.1lf, %.1lf).\n", fp[index].x, fp[index].y);
	}

	return 0;
}


/*
//POJ 1379 求点的最大距离的最小值
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<ctime>
#include<cstdlib>
using namespace std;

#define PI 3.14159265358
#define LL long long 
#define MAXN 1005


const double eps = 1e-3;
const double INF = 1e20;

int max(int a, int b)
{
	if (a > b) return a;
	return b;
}

class Point
{
public:
	Point()
	{
		maxDis = INF;
	}
	Point(double tx, double ty)
	{
		x = tx;
		y = ty;
		maxDis = INF;
	}

	double x, y, maxDis;
};

double dis(Point a, Point b)
{
	return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));
}

Point hole[MAXN], fp[MAXN];

int X, Y, N, L, P;
double delta;

int main()
{
	//	Point a(0, 0), b(3, 4);
	//	cout << dis(a, b);
	//	cout<<"- -"<<endl;
	int T;
	cin >> T;
	while (T--)
	{
		cin >> X >> Y >> N;
		L = 25, P = 15, delta = double(max(X, Y)) / (sqrt(1.0*N));
		srand((unsigned int)time(NULL));
		for (int i = 0; i <= N - 1; i++)
		{
			cin >> hole[i].x >> hole[i].y;
		}
		for (int i = 0; i <= P - 1; i++)
		{
			//			cout << "- -" << endl;
			fp[i].x = double(rand() % 1000 + 1) / 1000 * X;
			fp[i].y = double(rand() % 1000 + 1) / 1000 * Y;
			fp[i].maxDis = INF;
			for (int j = 0; j <= N - 1; j++)
			{
				double tp = dis(fp[i], hole[j]);
				if (fp[i].maxDis > tp) fp[i].maxDis = tp;//找最大距离,用-1
			}
		}
			
		while (delta>eps)
		{
				for (int i = 0; i <= P - 1;i++)
				{
		//			Point tmp = fp[i];
					for (int k = 1; k <= L; k++)
					{
						double alpha = double(rand() % 1000+1) / 1000.0 * 2 * PI;
						Point tp;
						tp.x = fp[i].x + cos(alpha)*delta;
						tp.y = fp[i].y + sin(alpha)*delta;
						if (tp.x<0 || tp.x>X || tp.y<0 || tp.y>Y) continue;
						tp.maxDis = INF;
						for (int j = 0; j <= N - 1; j++)
						{
							double distp = dis(tp, hole[j]);
							if (tp.maxDis > distp) tp.maxDis = distp;
						}
						//					if (tp.x>=300||tp.y>=300)
						//					printf("##---(%.1lf,%.1lf)---%.1lf\n", tp.x, tp.y, tp.maxDis);
						if (tp.maxDis > fp[i].maxDis)
						{
							fp[i].maxDis = tp.maxDis;
							fp[i].x = tp.x;
							fp[i].y = tp.y;
						}
					}	
				}

				delta *= 0.8;
		}
	

		int index = 0;
		for (int i = 0; i <= P - 1; i++)
		{
			//		printf("---(%.1lf,%.1lf)---%.1lf\n", fp[i].x, fp[i].y, fp[i].maxDis);
			if (fp[index].maxDis < fp[i].maxDis) index = i;
		}
		//	printf("(%.1lf,%.1lf).\n%.1lf\n", fp[index].x, fp[index].y, fp[index].maxDis);
		printf("The safest point is (%.1lf, %.1lf).\n", fp[index].x, fp[index].y);
	}

	return 0;
}
*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值