[关键字]:随机化搜索 模拟退火
[题目大意]:给出n个点,找出一个距离所有点之和最小的点,输出距离。
//===============================================================================
[分析]:同样是随机化的方法,只是在把没个点随机移动时有小小的变动。poj1379是使用得随机一个角度x然后利用t*cos(x)和t*sin(x)来处理随机走到的位置,而这道题因为没有了边界的限制,可以用以2t为长以要移动的点位中心的正方形中随机一个移动的位置来求最优值。至于具体退火算法步骤可以看poj1379或http://www.clarkok.com/blog/?p=357
//================================================================================
[代码]:
View Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
const int NUM=20;
const int TUM=20;
const int RD=1000;
const int MAXN=150;
const double ZERO=0.1;
const double det=0.7;
struct node
{
double x,y,dat;
}a[MAXN],MIN,MAX,b[MAXN];
int n;
double ans;
double dis(node c)
{
double sum=0;
for (int i=1;i<=n;++i)
sum+=sqrt((a[i].x-c.x)*(a[i].x-c.x)+(a[i].y-c.y)*(a[i].y-c.y));
return sum;
}
double random()
{
double sum=(rand()%(RD+1))*(1.0/RD);
return sum;
}
node GET(node x,node y)
{
node c;
//printf("%lf %lf %lf",x.x,y.x,y.x-x.x);
//system("pause");
c.x=x.x+(y.x-x.x)*random(),c.y=x.y+(y.y-x.y)*random();
//printf("%lf %lf\n",c.x,c.y);
//system("pause");
c.dat=dis(c);
return c;
}
bool Init()
{
if (scanf("%d",&n)==EOF) return 0;
MIN.x=MIN.y=100000;
MAX.x=MAX.y=-100000;
for (int i=1;i<=n;++i)
{
scanf("%lf%lf",&a[i].x,&a[i].y);
if (a[i].x<MIN.x) MIN.x=a[i].x;if (a[i].y<MIN.y) MIN.y=a[i].y;
if (a[i].x>MAX.x) MAX.x=a[i].x;if (a[i].y>MAX.y) MAX.y=a[i].y;
}
for (int i=1;i<=NUM;++i) b[i]=GET(MIN,MAX);//,printf("%lf %lf %lf\n",b[i].x,b[i].y,b[i].dat);
//printf("%lf %lf %lf %lf\n",MIN.x,MIN.y,MAX.x,MAX.y);
return 1;
}
void Solve(double T)
{
node t,x,y;
for (double i=T;i>=ZERO;i*=det)
for (int j=1;j<=NUM;++j)
for (int k=1;k<=TUM;++k)
{
x.x=b[j].x-i,x.y=b[j].y-i;
y.x=b[j].x+i,y.y=b[j].y+i;
t=GET(x,y);
//printf("%lf %lf %lf %lf %lf\n",x.x,x.y,y.x,y.y,i);
if (t.dat<b[j].dat) b[j]=t;
}
ans=1e10;
for (int i=1;i<=NUM;++i)
{
if (ans>b[i].dat) ans=b[i].dat;
//printf("%lf\n",b[i].dat);
}
printf("%.0lf\n",ans);
}
int main()
{
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
while (Init()) Solve(max(MAX.x-MIN.x,MAX.y-MIN.y));
return 0;
}