POJ - 2069 Super Star & HDU - 3007 Buried memory

模拟退火求最小球覆盖和最小圆覆盖

原本在我的认识中,模拟退火一定要有一个随机化在里面。

但是有些模拟退火,你可以清楚地意识到答案是可以向某个方向逼近的,这个时候就不用随机了。

比如像第一道题POJ 2069,这道题求的就是最小球覆盖。

对于任意的初始点,我们都能算出以当前点作为圆心的覆盖半径是多少。

显然,决定这条半径多长的,是所有点中离圆心最远的。

那么我们是不是可以越来越靠近这个最远的点,使得最远的距离最小,也就是球的半径能最小?

答案是肯定的,我们直接慢慢地更新答案即可。

同时我们也套上模拟退火的板子,用一个T来表示那一步移动的步长。

最小圆覆盖当然比三维情况要简单,所以能理解上面的,那道题也就顺便切掉了。

分别附上这两道题的代码:

POJ 2069

#include<cstdio>
#include<cmath>
const int maxn = 35;
const double delta = 0.98;
struct Point
{
	double x, y, z;
} s[maxn];
double ansx, ansy, ansz, ans;
int n;

inline double sq(double x)
{
	 return x * x;
}
double dist(double x, double y, double z, double xx, double yy, double zz)
{
	return sqrt(sq(x - xx) + sq(y - yy) + sq(z - zz));
}

int main()
{
	while(scanf("%d", &n) == 1 && n)
	{
		ansx = ansy = ansz = 0;// 取平均值过不了是最骚的
		for(int i = 1; i <= n; i++)
		{
			scanf("%lf%lf%lf", &s[i].x, &s[i].y, &s[i].z);
		}
		for(double T = 100; T > 1e-15; T = T * delta)// 话说这道题卡精度
		{
			double maxdist = -1e15; int idx = -1;
			for(int i = 1; i <= n; i++)
			{
				double temp = dist(ansx, ansy, ansz, s[i].x, s[i].y, s[i].z);
				if(temp > maxdist)
				{
					maxdist = temp; idx = i;
				}
			}
			ans = maxdist;
			ansx += (s[idx].x - ansx) / maxdist * T;
			ansy += (s[idx].y - ansy) / maxdist * T;
			ansz += (s[idx].z - ansz) / maxdist * T;
		}
		printf("%.5lf\n", ans);
	}
	return 0;
}

HDU 3007

#include<cstdio>
#include<cmath>
const int maxn = 505;
struct Nodes
{
	double x, y;
} s[maxn];
double ansx, ansy;
int n;
inline double sq(double x)
{
	return x * x;
}
double dist(double x, double y, double xx, double yy)
{
	return sqrt(sq(x - xx) + sq(y - yy));
}
int main()
{
	while(scanf("%d", &n) == 1 && n)
	{
		ansx = ansy = 0;
		for(int i = 1; i <= n; i++)
		{
			scanf("%lf%lf", &s[i].x, &s[i].y);
			ansx += s[i].x; ansy += s[i].y;
		}
		ansx /= n; ansy /= n;
		const double delta = 0.98;
		for(double T = 2018; T > 1e-10; T *= delta)
		{
			double maxr = -1e10; int idx = -1;
			for(int i = 1; i <= n; i++)
			{
				double temp = dist(ansx, ansy, s[i].x, s[i].y);
				if(temp > maxr)
				{
					maxr = temp; idx = i;
				}
			}
			ansx += (s[idx].x - ansx) / maxr * T;
			ansy += (s[idx].y - ansy) / maxr * T;
		}
		printf("%.2lf %.2lf %.2lf\n", ansx, ansy, dist(ansx, ansy, s[1].x, s[1].y));
	}
	return 0;
}
posted @ 2018-11-06 09:29  Garen-Wang  阅读(107)  评论(0编辑  收藏  举报