poj2420

模拟退火算法,其实不如说随机化变步长的贪心,向四周搜索,如果碰到更小的则把它作为更优解。

poj2420_第1张图片

本题代码中费马点部分可作为模版使用。

#include <iostream>
#include <stdio.h>
#include <math.h>

#define MAX_NUM 128

struct point
{
	double x;
	double y;
};

double distance(point p1, point p2){
	return sqrt((p1.x - p2.x)*(p1.x - p2.x) + (p1.y - p2.y)*(p1.y - p2.y));
}
//多边形费马点,点集pt,大小n,传入ptres作为费马点这一点,返回值是所有点到费马点的距离
double fermat_point(point pt [], int n, point & ptres)
{
	point u, v;
	double step = 0.0, curlen, explen, minlen;
	int i, j, k, idx;
	bool flag;
	u.x = u.y = v.x = v.y = 0.0;
	for (i = 0; i < n; ++i)
	{
		step += fabs(pt[i].x) + fabs(pt[i].y);
		u.x += pt[i].x;
		u.y += pt[i].y;
	}
	u.x /= n;
	u.y /= n;
	flag = 0;
	while (step > 1e-10)
	{
		for (k = 0; k < 10; step /= 2, ++k)
			for (i = -1; i <= 1; ++i)
				for (j = -1; j <= 1; ++j)
				{
					v.x = u.x + step*i;
					v.y = u.y + step*j;
					curlen = explen = 0.0;
					for (idx = 0; idx < n; ++idx)
					{
						curlen += distance(u, pt[idx]);
						explen += distance(v, pt[idx]);
					}
					if (curlen > explen)
					{
						u = v;
						minlen = explen;
						flag = 1;
					}
				}
	}
	ptres = u;
	return flag ? minlen : curlen;
}

int main()
{
	//freopen("in.txt", "r", stdin);
	//freopen("out.txt", "w", stdout);

	int n, i;
	double res;
	point pt[MAX_NUM], ptres;
	while (std::cin>>n)
	{
		for (i = 0; i < n; ++i)
		{
			std::cin>>pt[i].x>>pt[i].y;
		}
		res = fermat_point(pt, n, ptres);
		//std::cout << ptres.x << ' ' << ptres.y << std::endl;
		if (res - (int) (res) > 0.5)
			printf("%d\n", (int) (res + 1));
		else
			printf("%d\n", (int) (res));
	}
}


你可能感兴趣的:(计算几何学,ACM题解报告)