题目链接
http://www.lydsy.com/JudgeOnline/problem.php?id=3680
思路
非常裸的模拟退火。。。
但是参数很难调,随机数写挫了也会错。。。
代码
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <cmath>
#define MAXN 10100 //!!!!!
#define INF 1e20
#define EPS 1e-3
using namespace std;
int n;
double minans=INF; //最小距离之和
struct Point
{
double x,y,weight;
}points[MAXN],start,cg;
double dist(Point a,Point b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double calc(Point center) //计算以center为重心到各点加权距离和
{
double ans=0;
for(int i=1;i<=n;i++)
ans+=points[i].weight*dist(points[i],center);
if(ans<minans)
{
minans=ans;
cg=center;
}
return ans;
}
double Rand()
{
return (double)(rand()%1000)/1000;
}
void SA(Point now)
{
minans=INF;
double T=1000000;
while(T>EPS)
{
Point next;
next.x=now.x+(Rand()*2-1)*T;
next.y=now.y+(Rand()*2-1)*T;
double dE=calc(now)-calc(next);
if(dE>0||exp(dE/T)>Rand()) now=next;
T*=0.993;
}
for(int i=1;i<=1000;i++) //随机1000次小范围移动
{
Point next;
next.x=cg.x+(Rand()*2-1)*T; //!!!
next.y=cg.y+(Rand()*2-1)*T; //!!!!
calc(next);
}
}
int main()
{
srand(23333333);
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%lf%lf%lf",&points[i].x,&points[i].y,&points[i].weight);
start.x+=points[i].x;
start.y+=points[i].y;
}
start.x/=n,start.y/=n;
SA(start);
printf("%.3lf %.3lf\n",cg.x,cg.y);
return 0;
}