1. 程式人生 > 實用技巧 >【POJ 2420】A Star not a Tree?

【POJ 2420】A Star not a Tree?

題目

題目連結:http://poj.org/problem?id=2420
給定一個 \(n\) 邊形所有頂點座標 \(x,y\),求其費馬點到所有頂點距離和。

費馬點是指到多邊形所有頂點距離和最小的點。

思路

模擬退火,每次在目前最優解附近隨機點。暴力 check 即可。

程式碼

#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int N=110;
const double delta=0.996;
int Q,n,sumx,sumy,X[N],Y[N];
double sx,sy,ans,sum;

double work(double x,double y)
{
	double sum=0;
	for (int i=1;i<=n;i++)
		sum+=sqrt((x-X[i])*(x-X[i])+(y-Y[i])*(y-Y[i]));
	return sum;
}

void solve()
{
	srand(rand());
	double t0=8000,t1=1e-14;
	while (t0>t1)
	{
		double x=sx+(rand()*2-RAND_MAX)*t0;
		double y=sy+(rand()*2-RAND_MAX)*t0;
		double sum=work(x,y);
		if (sum<ans) ans=sum;
		else if (exp(-(sum-ans)/t0)>1.0*rand()/RAND_MAX) sx=x,sy=y;
		t0*=delta;
	}
}

int main()
{
	while (scanf("%d",&n)!=EOF)
	{
		srand(n+sumx);
		sumx=sumy=0;
		for (int i=1;i<=n;i++)
		{
			scanf("%d%d",&X[i],&Y[i]);
			sumx+=X[i]; sumy+=Y[i];
		}
		sx=1.0*sumx/n; sy=1.0*sumy/n;
		ans=work(sx,sy);
		solve(); solve(); solve();
		printf("%d\n",(int)ans);
	}
	return 0;
}