JZOJ 5267. 费马点问题

来源:互联网 发布:mac 双定制粉底液 肤质 编辑:程序博客网 时间:2024/06/08 12:04

Description

给n个点,每个点的横纵坐标为[0,10000]内的整数,找出一个点,使这个点到其他所有点的距离之和最小,也就是求费马点。
找到的点可能是小数。

Input

第一行一个整数n表示点数,后面n行每行两个整数,表示点的坐标。

Output

第一行一个整数n表示点数,后面n行每行两个整数,表示点的坐标。

Sample Input

5
8 8
10 8
7 10
8 6
5 7

Sample Output

9.40

Data Constraint

对于30%数据n<=10
​对于100%数据n≤100

Solution

  • 经典的费马点问题,直接使用模拟退火算法——一个完完全全的贪心求近似最优解的算法。

  • 引用一下度娘:

模拟退火算法(Simulate Anneal,SA)是一种通用概率演算法,用来在一个大的搜寻空间内找寻命题的最优解。模拟退火是由S.Kirkpatrick, C.D.Gelatt和M.P.Vecchi1983年所发明的。V.Čern&yacute;在1985年也独立发明此演算法。模拟退火算法是解决TSP问题的有效方法之一。模拟退火的出发点是基于物理中固体物质的退火过程与一般组合优化问题之间的相似性。模拟退火算法是一种通用的优化算法,其物理退火过程由加温过程、等温过程、冷却过程这三部分组成。
  • 进入正题,我们在范围内随机 M=30 个可能点,

  • 并设置限制 lim=104 ,降温率 delta=0.99 ,温度下限阈值 Tmin=0.01

  • 每次处理一个可能点 (xi,yi) ,那么在矩形 (x±lim,y±lim) 中随机出一个点 (xi,yi)

  • O(N) 计算一次 (xi,yi) 的答案,若能更新答案,就将 (xi,yi) 移到 (xi,yi)

  • 最后把 lim=limdelta ,则继续处理每个可能点,直到 lim<=Tmin 时停止。

Code

#include<cstdio>#include<cstdlib>#include<cmath>#include<ctime>using namespace std;const int N=10001,M=31,way[4][2]={{1,1},{-1,1},{-1,-1},{1,-1}};struct data{    double x,y;}a[N],b[M],t;int n,mnx,mxx,mny,mxy;double ans=1e9;inline int read(){    int X=0,w=1; char ch=0;    while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}    while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();    return X*w;}inline double get(){    double s=0;    for(int i=1;i<=n;i++) s+=sqrt((t.x-a[i].x)*(t.x-a[i].x)+(t.y-a[i].y)*(t.y-a[i].y));    return s;}inline int random(int x,int y){    return x+rand()%(y-x+1);}int main(){    srand(time(NULL));    n=read();    mnx=mny=N;    for(int i=1;i<=n;i++)    {        a[i].x=read(),a[i].y=read();        if(a[i].x<mnx) mnx=a[i].x;        if(a[i].x>mxx) mxx=a[i].x;        if(a[i].y<mny) mny=a[i].y;        if(a[i].y>mxy) mxy=a[i].y;    }    for(int i=1;i<M;i++)    {        b[i].x=random(mnx*N,mxx*N)*1.0/N;        b[i].y=random(mny*N,mxy*N)*1.0/N;        t=b[i];        double p=get();        if(p<ans) ans=p;    }    for(double lim=N;lim>0.01;lim*=0.99)        for(int i=1;i<M;i++)        {            t.x=random((b[i].x-lim)*N,(b[i].x+lim)*N)*1.0/N;            t.y=random((b[i].y-lim)*N,(b[i].y+lim)*N)*1.0/N;            double p=get();            if(p<ans) ans=p,b[i]=t;        }    printf("%.2lf",ans);    return 0;}
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 头朝下墩了脖子怎么办 两岁摔倒头着地怎么办 马桶大便冲不下去怎么办 脚丫吧里起泡痒怎么办 脚受伤后肿了怎么办 摔到了腿受伤了怎么办 骑车摔倒了肿了怎么办 生活大冒险老婆失踪了怎么办 手机qq图裂了怎么办 qq发的图裂了怎么办 抖音账号搬运多怎么办 别人搜不到我QQ怎么办 qq号被限制解封怎么办 买的桌子会晃怎么办 车子座椅皮坏了怎么办 裤子被椅子刮了怎么办 脚麻了被别人动怎么办 毛孔又粗又黑怎么办 手臂睡觉压麻了怎么办 睡觉压的胳膊麻怎么办 摔跤摔到腰肿了怎么办 牛奶喝多了拉稀怎么办 doc文档下载是乱码怎么办 家人被教练技术骗了怎么办 十个月宝宝不爱喝水怎么办 离婚后孩子找爸爸怎么办 离婚后孩子要找爸爸怎么办 断奶期间胸涨的难受怎么办 断奶胸涨的很疼怎么办 过了麦季身上老痒怎么办 过麦时候皮肤痒怎么办 颈部起红疙瘩痒怎么办 脚底痒身上痒该怎么办 生完孩子屁股疼怎么办 pr打开工程文件无响应怎么办 娃娃和老师有隔阂了怎么办 大人字写得不好怎么办 不会写好看的字怎么办 无限量流量限速了怎么办 长期化妆后皮肤变黄怎么办 手机密码忘记了打不开怎么办