HDU3694 Fermat Point in Quadrangle 多边形费马点结论

HDU3694
前面说了一大推都没什么用,最后是求四边形的一个fermat点。
多边形的fermat点是欧拉平面上的一个点到多边形每个点的距离之和最小的点
四边形的fermat点在四个顶点与对角线交点值5个点中较小的那个,直接套模板计算取最小值即可
在判断多边形的对角线时小小用了一下极角排序
AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
const double eps=1e-8;
using namespace std;
int sgn(double x){
    if(fabs(x)<eps)
        return 0;
    return x>0 ?1 :-1;
}
struct point{
    double x,y;
    point() {}
    point(double _x,double _y){
        x=_x;
        y=_y;
    }
};
point p[10];
point operator - (point A,point B){
    return point(A.x-B.x,A.y-B.y);
}
int operator ^ (point A,point B){
    return A.x*B.y-A.y*B.x;
}
int operator * (point A,point B){
    return A.x*B.x+A.y*B.y;
}
bool operator < (point A,point B){
    return A.x<B.x || A.x==B.x && A.y<B.y;
}
bool operator == (point a,point b){
    return sgn(a.x-b.x)==0 && sgn(a.y-b.y)==0;
}
double dis(point a,point b){
    return hypot(a.x-b.x,a.y-b.y);
}
bool cmp(point a,point b){ //极角排序函数
        int d=sgn((a-p[0])^(b-p[0]));
        if(d==0&&sgn(dis(a,p[0])-dis(b,p[0])) < 0 || d>0)//共线时取较近的点
            return true;
        return false;
}
struct line{
    point s,e;
    line() {}
    line (point _s,point _e){
        s=_s;
        e=_e;
    }
    point crosspoint(line v){
        double a1=(v.e-v.s)^(s-v.s);
        double a2=(v.e-v.s)^(e-v.s);
        return point((s.x*a2-e.x*a1)/(a2-a1),(s.y*a2-e.y*a1)/(a2-a1));
    }
};
double solve(){
    for(int i=0;i<4;i++)
        if(p[i]<p[0])
            swap(p[i],p[0]);
    sort(p+1,p+4,cmp);
    double m=50000.0,tmp;
    for(int i=0;i<4;i++){
        tmp=dis(p[i],p[(i+1)%4])+dis(p[i],p[(i+2)%4])+dis(p[i],p[(i+3)%4]);
        if(tmp<m)
            m=tmp;
    }
    line l1=line(p[0],p[2]);
    line l2=line(p[1],p[3]);
    point f=l1.crosspoint(l2);
    tmp=dis(f,p[0])+dis(f,p[1])+dis(f,p[2])+dis(f,p[3]);
    if(tmp<m)
        m=tmp;
    return m;
}
int main(){
    //freopen("e.txt","r",stdin);
    while(cin>>p[0].x>>p[0].y>>p[1].x>>p[1].y>>p[2].x>>p[2].y>>p[3].x>>p[3].y){
        if(p[0].x==-1 && p[0].y==-1 && p[1].x==-1 && p[1].y==-1 && p[2].x==-1 && p[2].y==-1 && p[3].x==-1 && p[3].y==-1)
            break;
        double ans=solve();
        printf("%.4lf\n",ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值