LA3890 Most Distant Point from the Sea 二分+半平面交

本文介绍了一种计算凸多边形内切圆半径的方法,通过二分搜索距离并验证由该距离缩放后的半平面交是否为空来确定最大内切圆半径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        一个凸多边形的岛,求岛上距离海岸最远的距离有多远。

         二分距离,然后收缩原直线围成的范围,也就是新的n条直线的半平面交是否为空,不为空就是可行的距离,否则就是不可行的。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
typedef double type;
using namespace std;
const double PI=acos(-1.0);
const double eps=1e-10;

struct Point
{
    type x,y;
    Point(){}
    Point(type a,type b)
    {
        x=a;
        y=b;
    }
    void read()
    {
        scanf("%lf%lf",&x,&y);
    }
    void print()
    {
        printf("%.6lf %.6lf",x,y);
    }

};
typedef Point Vector;
Vector operator + (Vector A,Vector B)
{
    return Vector(A.x+B.x,A.y+B.y);
}
Vector operator - (Point A,Point B)
{
    return Vector(A.x-B.x,A.y-B.y);
}
Vector operator * (Vector A,type p)
{
    return Vector(A.x*p,A.y*p);
}
Vector operator / (Vector A,type p)
{
    return Vector(A.x/p,A.y/p);
}
bool operator < (const Point &a,const Point &b)
{
    return a.x<b.x || (a.x==b.x && a.y<b.y);
}

int dcmp(double x)
{
    if (fabs(x)<eps) return 0;
    else return x<0?-1:1;
}
bool operator == (const Point& a,const Point b)
{
    return dcmp(a.x-b.x)==0 && dcmp(a.y-b.y)==0;
}
//atan2(x,y) :向量(x,y)的极角,即从x轴正半轴旋转到该向量方向所需要的角度。
type Dot(Vector A,Vector B)
{
    return A.x*B.x+A.y*B.y;
}
type Cross(Vector A,Vector B)
{
    return A.x*B.y-A.y*B.x;
}
type Length(Vector A)
{
    return sqrt(Dot(A,A));
}
type Angle(Vector A,Vector B)
{
    return acos(Dot(A,B))/Length(A)/Length(B);
}

type Area2(Point A,Point B,Point C)
{
    return Cross(B-A,C-A);
}
Vector Rotate(Vector A,double rad)
{
    return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));
}

Vector Normal(Vector A)//单位法线,左转90度,长度归一
{
    double L=Length(A);
    return Vector(-A.y/L,A.x/L);
}

Point GetLineIntersection(Point P,Vector v,Point Q,Vector w)
{
    Vector u=P-Q;
    double t=Cross(w,u)/Cross(v,w);
    return P+v*t;
}

double DistanceToLine(Point P,Point A,Point B)
{
    Vector v1=B-A,v2=P-A;
    return fabs(Cross(v1,v2))/Length(v1);
}
double DistanceToSegment(Point P,Point A,Point B)
{
    if (A==B) return Length(P-A);
    Vector v1=B-A,v2=P-A,v3=P-B;
    if (dcmp(Dot(v1,v2))<0) return Length(v2);
    else if (dcmp(Dot(v1,v3))>0) return Length(v3);
    else return fabs(Cross(v1,v2))/Length(v1);
}
Point GetLineProjection(Point P,Point A,Point B)//P在AB上的投影
{
    Vector v=B-A;
    return A+v*(Dot(v,P-A)/Dot(v,v));
}

bool SegmentProperIntersection(Point a1,Point a2,Point b1,Point b2)
{
    double c1=Cross(a2-a1,b1-a1),c2=Cross(a2-a1,b2-a1),
    c3=Cross(b2-b1,a1-b1),c4=Cross(b2-b1,a2-b1);
    return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0;
}

bool OnSegment(Point p,Point a1,Point a2)
{
    return dcmp(Cross(a1-p,a2-p))==0 && dcmp(Dot(a1-p,a2-p))<0;
}

double ConvexPolygonArea(Point* p,int n)//多边形面积
{
    double area=0;
    for (int i=1; i<n-1; i++)
    area+=Cross(p[i]-p[0],p[i+1]-p[0]);
    return area/2.0;
}
double PolygonArea(Point* p,int n)//有向面积
{
    double area=0;
    for (int i=1; i<n-1; i++)
    area+=Cross(p[i]-p[0],p[i+1]-p[0]);
    return area/2.0;
}
struct Line
{
    Point p;
    Vector v;
    double ang;
    Line(){};
    Line(Point PP,Vector vv)
    {
        p=PP;
        v=vv;
        ang=atan2(v.y,v.x);
    }
    bool operator< (const Line& L)const
    {
        return ang<L.ang;
    }
    Point point(double t)
    {
        return p+v*t;
    }
};
struct Circle
{
    Point c;
    double r;
    Circle()
    {
    }
    Circle(Point cc,double rr)
    {
        c=cc;
        r=rr;
    }
    Point point(double a)
    {
        return Point(c.x+cos(a)*r,c.y+sin(a)*r);
    }
};
int getLineCircleIntersection(Line L,Circle C,double& t1,double &t2,vector<Point>& sol)
{
    double a=L.v.x, b=L.p.x-C.c.x, c=L.v.y, d=L.p.y-C.c.y;
    double e=a*a+c*c,f=2*(a*b+c*d), g=b*b+d*d-C.r*C.r;
    double delta=f*f-4*e*g;//判别式
    if (dcmp(delta)<0) return 0;//相离
    if (dcmp(delta)==0)
    {
        t1=t2=-f/(2*e);
        sol.push_back(L.point(t1));
        return 1;
    }//相切
    t1=(-f-sqrt(delta))/(2*e); sol.push_back(L.point(t1));
    t2=(-f+sqrt(delta))/(2*e); sol.push_back(L.point(t2));
    return 2;
}
double angle(Vector v)//向量极角
{
    return atan2(v.y,v.x);
}
int getCircleCircleIntersection(Circle C1,Circle C2,vector<Point>& sol)
{
    double d = Length(C1.c-C2.c);
    if (dcmp(d)==0)
    {
        if (dcmp(C1.r-C2.r)==0) return -1;
        return 0;
    }
    if (dcmp(C1.r+C2.r-d)<0) return 0;
    if (dcmp(fabs(C1.r-C2.r)-d)>0) return 0;
    double a=angle(C2.c-C1.c);
    double da= acos((C1.r*C1.r+d*d-C2.r*C2.r)/(2*C1.r*d));
    Point p1=C1.point(a-da),p2=C1.point(a+da);
    sol.push_back(p1);
    if (p1==p2) return 1;
    sol.push_back(p2);
    return 2;
}
int getTangents(Point p,Circle C,Vector* v)
{
    Vector u=C.c-p;
    double dist=Length(u);
    if (dist<C.r) return 0;
    else if (dcmp(dist-C.r)==0)
    {
        v[0]=Rotate(u,PI/2);
        return 1;
    }
    else
    {
        double ang=asin(C.r/dist);
        v[0]=Rotate(u,-ang);
        v[1]=Rotate(u,+ang);
        return 2;
    }
}
int getTangents(Circle A,Circle B,Point* a,Point* b)
{
    int cnt=0;
    if (A.r<B.r)
    {
        swap(A,B); swap(a,b);
    }
    int d2=(A.c.x-B.c.x)*(A.c.x-B.c.x)+(A.c.y-B.c.y)*(A.c.y-B.c.y);
    int rdiff=A.r-B.r;
    int rsum=A.r+B.r;
    if (d2<rdiff*rdiff) return 0;
    double base=atan2(B.c.y-A.c.y,B.c.x-A.c.x);
    if (d2==0 && A.r==B.r) return -1;

    if (d2==rdiff*rdiff)
    {
        a[cnt]=A.point(base); b[cnt]=B.point(base); cnt++;
        return 1;
    }
    double ang=acos((A.r-B.r)/sqrt((double)d2));
    a[cnt]=A.point(base+ang); b[cnt]=B.point(base+ang); cnt++;
    a[cnt]=A.point(base-ang); b[cnt]=B.point(base-ang); cnt++;
    if (d2==rsum*rsum)
    {
        a[cnt]=A.point(base); b[cnt]=B.point(PI+base); cnt++;
    }
    else if (d2>rsum*rsum)
    {
        double ang=acos((A.r+B.r)/sqrt((double)d2));
        a[cnt]=A.point(base+ang); b[cnt]=B.point(PI+base+ang); cnt++;
        a[cnt]=A.point(base-ang); b[cnt]=B.point(PI+base-ang); cnt++;
    }
    return cnt;
}
int isPointInpolygon(Point p,Point* poly,int n)
{
    int wn=0;
    for (int i=0; i<n; i++)
    {
        if (OnSegment(p,poly[i],poly[(i+1)%n]) || p==poly[i] || p==poly[(i+1)%n]) return -1;
        int k=dcmp(Cross(poly[(i+1)%n]-poly[i],p-poly[(i+1)%n]));
        int d1=dcmp(poly[i].y-p.y);
        int d2=dcmp(poly[(i+1)%n].y-p.y);
        if (k>0 && d1<=0 && d2>0) wn++;
        if (k<0 && d2<=0 && d1>0) wn--;
    }
    if (wn!=0) return 1;
    else return 0;
}
int ConvexHull(Point *p, int n,Point *ch)
{
    sort(p,p+n);
    int m=0;
    for (int i=0; i<n; i++)
    {
        while(m>1 && Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--;
        ch[m++]=p[i];
    }
    int k=m;
    for (int i=n-2; i>=0; i--)
    {
        while(m>k && Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--;
        ch[m++]=p[i];
    }
    if (n>1) m--;
    return m;
}
double rotating_calipers(Point *p,int n)
{
    int i,q=1;
    double ans=0;
    for (int i=0; i<n-1; i++)
    {
        while(Cross(p[q+1]-p[i+1],p[i]-p[i+1])>Cross(p[q]-p[i+1],p[i]-p[i+1]))
        {
            q=(q+1)%n;
        }
        ans=max(ans,max(Length(p[i]-p[q]),Length(p[i+1]-p[q])));
    }
    return ans*ans;
}
bool OnLeft(Line L,Point p)
{
    return Cross(L.v,p-L.p)>0;
}
//两直线交点
Point GetIntersection(Line a,Line b)
{
    Vector u=a.p-b.p;
    double t=Cross(b.v,u)/Cross(a.v,b.v);
    return a.p+a.v*t;
}
int HalfplaneIntersection(Line* L,int n,Point* poly)
{
    sort(L,L+n);
    int first,last;
    Point *p=new Point[n];
    Line *q=new Line[n];
    q[first=last=0] = L[0];
    for (int i=1; i<n; i++)
    {
        while(first<last && !OnLeft(L[i],p[last-1])) last--;
        while(first<last && !OnLeft(L[i],p[first])) first++;
        q[++last]=L[i];
        if (fabs(Cross(q[last].v,q[last-1].v))<eps)
        {
            last--;
            if (OnLeft(q[last],L[i].p)) q[last]=L[i];
        }
        if (first<last) p[last-1]=GetIntersection(q[last-1],q[last]);
    }
    while(first<last && !OnLeft(q[first],p[last-1])) last--;
    if (last-first<=1) return 0;//空集
    p[last]=GetIntersection(q[last],q[first]); //计算首尾两个半平面的交点

    int m=0;
    for (int i=first; i<=last; i++) poly[m++]=p[i];
    return m;
}

Point poly[300];
Vector v[300];
Vector vm[300];
Point ch[300];
int tt;
int m,n;
Line li[300];

int main()
{
//    freopen("in.txt","r",stdin);
    while(~scanf("%d",&n) && n)
    {
        for (int i=0; i<n; i++)
        poly[i].read();
        for (int i=0; i<n; i++)
        {
            int j=(i+1)%n;
            v[i]=poly[j]-poly[i];
            vm[i]=Normal(v[i]);
            vm[i]=vm[i]/Length(vm[i]);
        }
        double l=0,r=10000;
        while (fabs(r-l)>1e-7)
        {
            double mid=(l+r)/2.0;
            for (int i=0; i<n; i++)
            {

                li[i]=Line(poly[i]+vm[i]*mid,v[i]);
            }
            int ck=HalfplaneIntersection(li,n,ch);
            if (ck>0)
            {
                l=mid;
            }
            else r=mid;
        }
        printf("%.6lf\n",l);
    }
    return 0;
}


### SBX (Simulated Binary Crossover) in Genetic Algorithms Implementation and Usage In the context of genetic algorithms, crossover operations play a crucial role in generating new offspring from parent solutions. For continuous search spaces, Simulated Binary Crossover (SBX), proposed by K. Deb and R. B. Agarwal, is widely used due to its effectiveness[^1]. This operator mimics traditional one-point or two-point crossovers but adapts them specifically for real-valued parameters. #### Definition and Characteristics The primary characteristic of SBX lies in how it creates children that are closer to their parents compared with other methods like uniform mutation. The probability distribution function ensures this behavior while allowing occasional distant jumps within feasible bounds. Such properties make SBX particularly suitable when dealing with multi-objective optimization problems where maintaining diversity among population members remains essential. #### Mathematical Formulation Given two parent individuals \( P_1 \) and \( P_2 \), let us denote child individual as \( Q_i \). To generate each component value of these children: If both parents have identical values at some position i.e., \( p_{xi} = p_{yi} \): \[ q_i = p_xi \] Otherwise, Let's define β based on whether we want more exploration (\( u < 0.5 \)) or exploitation (\( u >= 0.5 \)): For \(u<0.5\), \[ \beta_q=2u^{(\frac{1}{n_c+1})}\] And for \(u>=0.5\), \[ \beta_q=(\frac{(2*(1-u))}{((1-u)^{\frac{n_c+1}{nc}})})^{\frac{1}{nc+1}}\] Where nc controls the spread factor around better parent solution during reproduction process. Finally calculate qi using following equations depending upon which parent has smaller xi : When px<=py, If rand()<0.5 then qi=0.5*((px+(βq)*(py−px))) Else qi=0.5*((py-(βq)*(py-px))) This procedure repeats until all components get assigned appropriate values forming complete offspring vectors Qi. ```matlab function [child1, child2] = sbx(parent1, parent2, eta_c) % Implementing simulated binary crossover operation between two parents dim = length(parent1); for i = 1:dim if rand() <= 0.5 % Calculate beta according to given formulae if abs(parent1(i)-parent2(i)) > eps if rand() < 0.5 beta = (2*rand())^(1/(eta_c+1)); else beta = (1/(2*(1-rand())))^(1/(eta_c+1)); end child1(i) = 0.5 * ((1 + beta)*min([parent1(i); parent2(i)]) ... +(1-beta)*max([parent1(i); parent2(i)])); child2(i) = 0.5 * ((1 - beta)*min([parent1(i); parent2(i)]) ... +(1+beta)*max([parent1(i); parent2(i)])); else child1(i) = parent1(i); child2(i) = parent2(i); end else child1(i) = parent1(i); child2(i) = parent2(i); end end ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值