模板(计算几何)

模板 专栏收录该内容
20 篇文章 0 订阅

几何

#define F double
F eps=1e-9;
const F pi=acos(-1);

struct point{
    F x,y;
    point(){}
    point(F x,F y):x(x),y(y){}
};
typedef point Vector;
typedef point Point;
Vector operator + (Vector a, Vector b){//向量加法
    return Vector(a.x + b.x, a.y + b.y);
}
Vector operator - (Vector a, Vector b){//向量减法
    return Vector(a.x - b.x, a.y - b.y);
}
Vector operator * (Vector a, F p){//向量数乘
    return Vector(a.x*p, a.y*p);
}
Vector operator / (Vector a, F p){//向量数除
    return Vector(a.x / p, a.y / p);
}
int dcmp(F x){//精度三态函数(>0,<0,=0)
    if (fabs(x) < eps)return 0;
    else if (x > 0)return 1;
    return -1;
}
bool operator == (const Point &a, const Point &b){//向量相等
    return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;
}
F Dot(Vector a, Vector b){//内积
    return a.x*b.x + a.y*b.y;
}
F Length(Vector a){//模
    return sqrt(Dot(a, a));
}
F Cross(Vector a, Vector b){//外积
    return a.x*b.y - a.y*b.x;
}
F Angle(Vector a, Vector b)
{ //夹角,弧度制
    F d2 = Dot(a, b) / Length(a) / Length(b);
    if (d2 < -1)
        d2 = -1;
    if (d2 > 1)
        d2 = 1;
    F ang = acos(d2);
    if (Cross(a, b) < 0)
    {
        ang = -ang;
    }
    return ang;
}
Vector Rotate(Vector a, F rad){//逆时针旋转
    return Vector(a.x*cos(rad) - a.y*sin(rad), a.x*sin(rad) + a.y*cos(rad));
}
Vector RotateTogether(Vector A1, Vector A2, Vector C){ //A1旋转到A2后,C应该旋转到哪里
    F ang = Angle(A1, A2);
    return Rotate(C, ang);
}
F Distance(Point a, Point b){//两点间距离
    return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));
}
F Area(Point a, Point b, Point c){//三角形面积
    return fabs(Cross(b - a, c - a) / 2);
}
bool Intersect(Point a, Point b, Point c, Point d){//线段相交(不包括端点)
    F t1 = Cross(c - a, d - a)*Cross(c - b, d - b);
    F t2 = Cross(a - c, b - c)*Cross(a - d, b - d);
    return dcmp(t1) < 0 && dcmp(t2) < 0;
}
bool StrictIntersect(Point a, Point b, Point c, Point d){ //线段相交(包括端点)
    return
        dcmp(max(a.x, b.x) - min(c.x, d.x)) >= 0
        && dcmp(max(c.x, d.x) - min(a.x, b.x)) >= 0
        && dcmp(max(a.y, b.y) - min(c.y, d.y)) >= 0
        && dcmp(max(c.y, d.y) - min(a.y, b.y)) >= 0
        && dcmp(Cross(c - a, d - a)*Cross(c - b, d - b)) <= 0
        && dcmp(Cross(a - c, b - c)*Cross(a - d, b - d)) <= 0;
}
F DistanceToLine(Point A, Point M, Point N){//点A到直线MN的距离,Error:MN=0
    return fabs(Cross(A - M, A - N) / Distance(M, N));
}
Point GetLineIntersection(Point P, Vector v, Point Q, Vector w){//两直线的交点
    Vector u = P - Q;
    F t = Cross(w, u) / Cross(v, w);
    return P + v * t;
}


//求多边形面积(叉积和计算法)
/*模板说明:P[]为多边形的所有顶点,下标为0~n-1,n为多边形边数*/
/*
Point P[1005];
int n;
F PolygonArea(){
    F sum = 0;
    Point O = Point(0, 0);
    for (int i = 0; i < n; i++)
        sum += Cross(P[i] - O, P[(i + 1) % n] - O);
    if (sum < 0)sum = -sum;
    return sum / 2;
}
*/

//求凸包
/*
point p[200009],ans[200009];
int n,top;
point Tmp;//选好的起点
bool cmp(point a,point b){
    F ans=Cross(a-Tmp,b-Tmp);
    if(dcmp(ans)==0)return dcmp(Distance(a,Tmp)-Distance(b,Tmp))<0;
    return ans>0;//表示a到b是逆时针转
}
void Graham(point p[],int n,point ans[],int &top){// 包含共线点
    for(int i=2;i<=n;i++){
        if(p[i].y<p[1].y||(dcmp(p[i].y-p[1].y)==0&&p[i].x<p[1].x))
            swap(p[1],p[i]);
    }
    Tmp=p[1];
    sort(p+2,p+1+n,cmp);
    ans[1]=p[1],ans[2]=p[2],top=2;
    for(int i=3;i<=n;i++){
        while(Cross(ans[top]-ans[top-1],p[i]-ans[top])<0)top--;
        ans[++top]=p[i];
    }
    //最后几个点如果是和p[1]在同一直线上的,那么会漏掉除最远的点以外的点
    for(int i=n-1;;i--){
        if(Cross(ans[top]-ans[1],p[i]-ans[1])!=0)break;
        ans[++top]=p[i];
    }
}
void Graham(point p[],int n,point ans[],int &top){// 去掉共线点
    if(n<3)return;
    for(int i=2;i<=n;i++){
        if(p[i].y<p[1].y||(dcmp(p[i].y-p[1].y)==0&&p[i].x<p[1].x))
            swap(p[1],p[i]);
    }
    Tmp=p[1];
    sort(p+2,p+1+n,cmp);
    ans[1]=p[1],ans[2]=p[2],top=2;
    for(int i=3;i<=n;i++){
        while(top>2&&dcmp(Cross(ans[top]-ans[top-1],p[i]-ans[top]))<=0)top--;
        ans[++top]=p[i];
        if(top>2&&dcmp(Cross(ans[top]-ans[top-1],ans[top-1]-ans[top-2]))==0)ans[top-1]=ans[top],--top;
    }
}
*/


struct Circle{
    Point c;
    F r;
    Point gpoint(F a){//基于圆心角求圆上一点坐标
        return Point(c.x + cos(a)*r, c.y + sin(a)*r);
    }
};
F Angle(Vector v1){
    if (v1.y >= 0)return Angle(v1, Vector(1.0, 0.0));
    else return 2 * pi - Angle(v1, Vector(1.0, 0.0));
}
/*
point a,b;
int GetCC(Circle C1, Circle C2){//求两圆交点
    F d = Length(C1.c - C2.c);
    if (dcmp(d) == 0)
    {
        if (dcmp(C1.r - C2.r) == 0)return -1;//重合
        else return 0;
    }
    if (dcmp(C1.r + C2.r - d) < 0)return 0;
    if (dcmp(fabs(C1.r - C2.r) - d) > 0)return 0;

    F a = Angle(C2.c - C1.c);
    F da = acos((C1.r*C1.r + d * d - C2.r*C2.r) / (2 * C1.r*d));
    Point p1 = C1.gpoint(a - da), p2 = C1.gpoint(a + da);
    if (p1 == p2){a=b=p1;return 1;}
    else {a=p1,b=p2;return 2;}
}
*/

极角排序

point Tmp;//选好的起点
int Quadrant(point a){// 象限
    if(a.x>0&&a.y>=0)  return 1;
    if(a.x<=0&&a.y>0)  return 2;
    if(a.x<0&&a.y<=0)  return 3;
    if(a.x>=0&&a.y<0)  return 4;
}
bool cmp(point a,point b){
    if(Quadrant(a-Tmp)==Quadrant(b-Tmp)){
        LL ans=Cross(a-Tmp,b-Tmp);
        if(ans==0)return a.x<b.x;
        return ans>0;
    }
    return Quadrant(a-Tmp)<Quadrant(b-Tmp);
}

最小圆覆盖

double eps=1e-9;
const double pi=acos(-1);

struct node{
    double x,y;
    node(){}
    node(double x,double y):x(x),y(y){}
};
typedef node Vector;
typedef node Point;
typedef node point;
Vector operator + (Vector a, Vector b){//向量加法
    return Vector(a.x + b.x, a.y + b.y);
}
Vector operator - (Vector a, Vector b){//向量减法
    return Vector(a.x - b.x, a.y - b.y);
}
Vector operator * (Vector a, double p){//向量数乘
    return Vector(a.x*p, a.y*p);
}
Vector operator / (Vector a, double p){//向量数除
    return Vector(a.x / p, a.y / p);
}
double Dot(Vector a, Vector b){//内积
    return a.x*b.x + a.y*b.y;
}
double Length(Vector a){//模
    return sqrt(Dot(a, a));
}
double Cross(Vector a, Vector b){//外积
    return a.x*b.y - a.y*b.x;
}
const double Pi=acos(-1.0);

int dcmp(double x)
{
    if (fabs(x)<eps) return 0;
    else if (x<0) return -1;
    else return 1;
}

double lenth(node a) {return sqrt(Dot(a,a));}

node rotate(node a,double t)    //向量旋转
{
    return node(a.x*cos(t)-a.y*sin(t),a.x*sin(t)+a.y*cos(t));
}

node jiao(node p,node v,node q,node w)
{
    node u=p-q;
    double t=Cross(w,u)/Cross(v,w);
    return p+v*t;
}

node get_c(node a,node b,node c)
{
    node p=(a+b)/2;    //ad中点
    node q=(a+c)/2;    //ac中点
    node v=rotate(b-a,Pi/2.0),w=rotate(c-a,Pi/2.0);   //中垂线的方向向量
    if (dcmp(Cross(v,w))==0)    //平行
    {
        if (dcmp(lenth(a-b)+lenth(b-c)-lenth(a-c))==0)
           return (a+c)/2;
        if (dcmp(lenth(b-a)+lenth(a-c)-lenth(b-c))==0)
           return (b+c)/2;
        if (dcmp(lenth(a-c)+lenth(c-b)-lenth(a-b))==0)
           return (a+b)/2;
    }
    return jiao(p,v,q,w);
}
node P[290];
node c;
double r;

void min_circular(int n)
{
    random_shuffle(P+1,P+n+1);    //随机化
    c=P[1],r=0;
    //c 圆心
    //r 半径
    for (int i=2;i<=n;i++)
        if (dcmp(lenth(c-P[i])-r)>0)    //不在圆内
        {
            c=P[i],r=0;
            for (int j=1;j<i;j++)
                if (dcmp(lenth(c-P[j])-r)>0)
                {
                    c=(P[i]+P[j])/2.0;
                    r=lenth(c-P[i]);
                    for (int k=1;k<j;k++)
                        if (dcmp(lenth(c-P[k])-r)>0)
                        {
                            c=get_c(P[i],P[j],P[k]);
                            r=lenth(c-P[i]);
                        }
                }
        }
}

int main(){
    freopen("robots.in","r",stdin);
    int t;scanf("%d",&t);
    while(t--){
        int n;double R,rr;scanf("%d%lf%lf",&n,&R,&rr);
        P[1]=node(0,0);
        n++;
        for(int i=2;i<=n;i++){
            double x,y;scanf("%lf%lf",&x,&y);
            P[i]=P[i-1]+node(x,y);
        }
        min_circular(n);
        printf("%.9f %.9f\n",-c.x,-c.y);
    }
}

K次圆覆盖

给出n个圆,问被i个圆覆盖的面积

#include<bits/stdc++.h>
using namespace std;
const int maxn=1009;
const double eps=1e-8;
const double pi=acos(-1);
int dcmp(double x) {
    return fabs(x)<eps?0:(x<0?-1:1);
}
struct circle {
    double x,y,r,angle;
    int d;
    circle() {}
    circle(double x,double y,double angle=0,int d=0)
        :x(x),y(y),angle(angle),d(d) {}
};
typedef circle Circle;
circle cir[maxn],tp[maxn<<1];
double area[maxn];

double sqr(double x){return x*x;}
double dis(circle a,circle b) {
    return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));
}
double cross(circle a,circle b,circle c) {
    return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
}
int CirCrossCir(Circle p1, double r1,Circle p2, double r2,Circle &cp1,Circle &cp2) {
    double mx = p2.x - p1.x, sx = p2.x + p1.x, mx2 = mx * mx;
    double my = p2.y - p1.y, sy = p2.y + p1.y, my2 = my * my;
    double sq = mx2 + my2, d = -(sq - sqr(r1 - r2)) * (sq - sqr(r1 + r2));
    if (d + eps < 0)
        return 0;
    if (d < eps)
        d = 0;
    else
        d = sqrt(d);
    double x = mx * ((r1 + r2) * (r1 - r2) + mx * sx) + sx * my2;
    double y = my * ((r1 + r2) * (r1 - r2) + my * sy) + sy * mx2;
    double dx = mx * d, dy = my * d;
    sq *= 2;
    cp1.x = (x - dy) / sq;
    cp1.y = (y + dx) / sq;
    cp2.x = (x + dy) / sq;
    cp2.y = (y - dx) / sq;
    if (d > eps)
        return 2;
    else
        return 1;
}

bool circmp(const Circle& u, const Circle& v) {
    return dcmp(u.r - v.r) < 0;
}
bool cmp(const Circle& u, const Circle& v) {
    if (dcmp(u.angle - v.angle))
        return u.angle < v.angle;
    return u.d > v.d;
}

double calc(Circle cir,Circle cp1,Circle cp2) {
    double ans = (cp2.angle - cp1.angle) * sqr(cir.r)
                 - cross(cir, cp1, cp2) + cross(Circle(0, 0), cp1, cp2);
    return ans / 2;
}

void CirUnion(Circle cir[], int n) {
    Circle cp1, cp2;
    sort(cir, cir + n, circmp);
    for (int i = 0; i < n; ++i)
        for (int j = i + 1; j < n; ++j)
            if (dcmp(dis(cir[i], cir[j]) + cir[i].r - cir[j].r) <= 0)
                cir[i].d++;
    for (int i = 0; i < n; ++i) {
        int tn = 0, cnt = 0;
        for (int j = 0; j < n; ++j) {
            if (i == j)
                continue;
            if (CirCrossCir(cir[i], cir[i].r, cir[j], cir[j].r,
                            cp2, cp1) < 2)
                continue;
            cp1.angle = atan2(cp1.y - cir[i].y, cp1.x - cir[i].x);
            cp2.angle = atan2(cp2.y - cir[i].y, cp2.x - cir[i].x);
            cp1.d = 1;
            tp[tn++] = cp1;
            cp2.d = -1;
            tp[tn++] = cp2;
            if (dcmp(cp1.angle - cp2.angle) > 0)
                cnt++;
        }
        tp[tn++] = Circle(cir[i].x - cir[i].r, cir[i].y, pi, -cnt);
        tp[tn++] = Circle(cir[i].x - cir[i].r, cir[i].y, -pi, cnt);
        sort(tp, tp + tn, cmp);
        int p, s = cir[i].d + tp[0].d;
        for (int j = 1; j < tn; ++j) {
            p = s;
            s += tp[j].d;
            area[p] += calc(cir[i], tp[j - 1], tp[j]);
        }
    }
}
int n;
void solve() {
    for(int i=0; i<n; i++){
        scanf("%lf%lf%lf", &cir[i].x, &cir[i].y, &cir[i].r);
        cir[i].d = 1;
    }
    memset(area,0,sizeof area);
    CirUnion(cir,n);
    for(int i=1; i<=n; i++) {
        area[i]-=area[i+1];
        printf("[%d] = %.3f\n", i, area[i]);
    }
}
int main() {
    while(scanf("%d",&n)!=EOF)
        solve();

    return 0;
}

半平面交

const int maxn = 1e3;
const double EPS = 1e-5;
int T, n;
struct Point {
    double x, y;
    Point(double x = 0, double y = 0):x(x),y(y){}
};
typedef Point Vector;
Vector operator - (Point a, Point b) {
    return Vector(b.x - a.x, b.y - a.y);
}
double operator ^ (Vector a, Vector b) {
    return a.x * b.y - a.y * b.x;   //叉乘
}
struct Line {
    Point s, e;
    Line() {}
    Line(Point a, Point b) {
        s = a, e = b;
    }
};
Point p[maxn];
Line L[maxn], que[maxn];

//得到极角角度
double getAngle(Vector a) {
    return atan2(a.y, a.x);
}

//得到极角角度
double getAngle(Line a) {
    return atan2(a.e.y - a.s.y, a.e.x - a.s.x);
}

//排序:极角小的排前面,极角相同时,最左边的排在最后面,以便去重
bool cmp(Line a, Line b) {
    Vector va = a.e - a.s, vb = b.e - b.s;
    double A =  getAngle(va), B = getAngle(vb);
    if (fabs(A - B) < EPS)
        return ((va) ^ (b.e - a.s)) >= 0;
    return A < B;
}

//得到两直线相交的交点
Point getIntersectPoint(Line a, Line b) {
    double a1 = a.s.y - a.e.y, b1 = a.e.x - a.s.x, c1 = a.s.x * a.e.y - a.e.x * a.s.y;
    double a2 = b.s.y - b.e.y, b2 = b.e.x - b.s.x, c2 = b.s.x * b.e.y - b.e.x * b.s.y;
    return Point((c1*b2-c2*b1)/(a2*b1-a1*b2), (a2*c1-a1*c2)/(a1*b2-a2*b1));
}

//判断 b,c 的交点是否在 a 的右边
bool onRight(Line a, Line b, Line c) {
    Point o = getIntersectPoint(b, c);
    if (((a.e - a.s) ^ (o - a.s)) < 0)
        return true;
    return false;
}

bool HalfPlaneIntersection() {
    // que的直线两两求交点再求面积就是核的面积
    sort(L, L + n, cmp);//排序
    int head = 0, tail = 0, cnt = 0;//模拟双端队列
    //去重,极角相同时取最后一个。
    for (int i = 0; i < n - 1; i++) {
        if (fabs(getAngle(L[i]) - getAngle(L[i + 1])) < EPS) {
            continue;
        }
        L[cnt++] = L[i];
    }
    L[cnt++] = L[n - 1];


    for (int i = 0; i < cnt; i++) {
        //判断新加入直线产生的影响
        while(tail - head > 1 && onRight(L[i], que[tail - 1], que[tail - 2]))
            tail--;
        while(tail - head > 1 && onRight(L[i], que[head], que[head + 1]))
            head++;
        que[tail++] = L[i];
    }
    //最后判断最先加入的直线和最后的直线的影响
    while(tail - head > 1 && onRight(que[head], que[tail - 1], que[tail - 2]))
        tail--;
    while(tail - head > 1 && onRight(que[tail - 1], que[head], que[head + 1]))
        head++;
    if (tail - head < 3)
        return false;
    return true;
}

//判断输入点的顺序,如果面积 <0,说明输入的点为逆时针,否则为顺时针
bool judge() {
    double ans = 0;
    for (int i = 1; i < n - 1; i++) {
        ans += ((p[i] - p[0]) ^ (p[i + 1] - p[0]));
    }
    return ans < 0;
}

int main() {
    scanf("%d", &T);
    while (T--) {
        scanf("%d", &n);
        for (int i = n - 1; i >= 0; i--) {
            scanf("%lf %lf", &p[i].x, &p[i].y);
        }

        if (judge()) {//判断输入顺序,保证逆时针连边。
            for (int i = 0; i < n; i++) {
                L[i] = Line(p[(i + 1)%n], p[i]);
            }
        } else {
            for (int i = 0; i < n; i++) {
                L[i] = Line(p[i], p[(i + 1)%n]);
            }
        }

        if (HalfPlaneIntersection())
            printf("YES\n");
        else
            printf("NO\n");
    }

    return 0;
}

平面最近点对

const double eps=1e-6;
int dcmp(double x){return fabs(x)<eps?0:(x>0?1:-1); }

struct point{
    double x,y;
    bool operator<(const point&A)const{
        return dcmp(x-A.x)==0?(y<A.y):(x<A.x);
    }
}e[maxn],tmp[maxn];
double dis(const point &a,const point &b){
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool cmp(const point &a,const point &b){
    return a.y<b.y;
}

#define mid (l+r>>1)
double d=1e18;
void cdq(int l,int r){
    if(l==r)return ;
    point M=e[mid];
    cdq(l,mid),cdq(mid+1,r);
    inplace_merge(e+l,e+mid+1,e+r+1,cmp);
    int top=0;
    rep(i,l,r){
        if(fabs(e[i].x-M.x)<=d)tmp[++top]=e[i];
    }
    rep(i,1,top){
        for(int j=i+1;j<=top&&fabs(tmp[i].y-tmp[j].y)<=d;j++){
            d=min(d,dis(tmp[i],tmp[j]));
        }
    }
}

int main(){
    int n=rd();
    rep(i,1,n)scanf("%lf%lf",&e[i].x,&e[i].y);
    sort(e+1,e+1+n);cdq(1,n);
    printf("%.4f\n",d);
    return 0;
}

旋转卡壳(最远对踵点对)

double RotateCalipers(P *p,int n){
    if(n==2)return LengthPow(p[1]-p[2]);
    double ans=-1;
    p[n+1]=p[1];
    // 保证q在i的前面,使得∠q_i+1_i小于180度
    int q=2;
    rep(i,1,n){// 枚举边i~i+1 , 如果q+1优于q , 旋转
        while(Cross(p[q]-p[i+1],p[i]-p[i+1])<Cross(p[q+1]-p[i+1],p[i]-p[i+1]))q=q%n+1;
        ans=max(ans,max(LengthPow(p[q]-p[i]),LengthPow(p[q+1]-p[i+1])));
    }
    return ans;
}

int main(){
    int n;
    while(scanf("%d",&n)!=EOF){
        rep(i,1,n){
            scanf("%lf%lf",&p[i].x,&p[i].y);
        }
        Graham(p,n,ans,top);
        printf("%.0f\n",round(RotateCalipers(ans,top)));
    }
}

旋转卡壳(凸包最近距离)

#define rep(i,a,b) for(int i=a;i<=b;i++)
double DistanceToSeg(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);
    if(dcmp(Dot(v1, v3)) > 0)
        return Length(v3);
    return fabs(Cross(v1, v2)) / Length(v1);
}
double SegDistancetoSeg(Point A, Point B, Point C, Point D) {
    return min(min(DistanceToSeg(C, A, B), DistanceToSeg(D, A, B)), 
    	min(DistanceToSeg(A, C, D), DistanceToSeg(B, C, D)));
}

double RotateCalipers(P *p1, int n1, P *p2, int n2) {
    int q1 = 1, q2 = 1; // q1 ymin, q2 ymax
    rep(i, 2, n1)
        if(p1[i].y < p1[q1].y)
            q1 = i;
    rep(i, 2, n2)
        if(p2[i].y > p2[q2].y)
            q2 = i;
    double ans = 1e18, tmp;
    p1[n1 + 1] = p1[1], p2[n2 + 1] = p2[1];
    rep(i, 1, n1) {
        while(dcmp(tmp = Cross(p1[q1 + 1] - p1[q1], p2[q2 + 1] - p1[q1]) -
                         Cross(p1[q1 + 1] - p1[q1], p2[q2] - p1[q1])) > 0)
            q2 = q2 % n2 + 1;
        if(dcmp(tmp) < 0)
            ans = min(ans, 
            	DistanceToSeg(p2[q2], p1[q1], p1[q1 + 1]));
        else
            ans = min(ans, 
            	SegDistancetoSeg(p1[q1], p1[q1 + 1], p2[q2], p2[q2 + 1]));
        q1 = q1 % n1 + 1;
    }
    return ans;
}

int main() {
    while(scanf("%d%d", &n1, &n2), n1 + n2) {
        rep(i, 1, n1)
        scanf("%lf%lf", &p1[i].x, &p1[i].y);
        rep(i, 1, n2)
        scanf("%lf%lf", &p2[i].x, &p2[i].y);
        printf("%.5f\n", min(RotateCalipers(p1, n1, p2, n2), 
        	RotateCalipers(p2, n2, p1, n1)));
    }
}

旋转卡壳(凸包最小外接矩形)

double RotateCalipers(P *p,int n){
    int r=2,l=2,up=2;
    double area=1e18;
    p[n+1]=p[1];
    rep(i,1,n){
        while(dcmp(Cross(p[i],p[i+1],p[up+1])-
            Cross(p[i],p[i+1],p[up])<=0))up=up%n+1;
        while(dcmp(Dot(p[i],p[i+1],p[r+1])-
            Dot(p[i],p[i+1],p[r])>0))r=r%n+1;
        if(i==1)l=r;
        while(dcmp(Dot(p[i],p[i+1],p[l+1])-
            Dot(p[i],p[i+1],p[l])<=0))l=l%n+1;
        double d=Distance(p[i],p[i+1])*Distance(p[i],p[i+1]);
        area=min(area, fabs(Cross(p[i],p[i+1],p[up]))*
            fabs(Dot(p[i],p[i+1],p[r])-Dot(p[i],p[i+1],p[l]))/d );
    }
    return area;
}

int main(){
    int t,cas=0;scanf("%d",&t);
    while(t--){
        printf("Case #%d:\n",++cas);
        int n;scanf("%d",&n);n<<=2;
        rep(i,1,n){
            scanf("%lf%lf",&p[i].x,&p[i].y);
        }
        Graham(p,n,ans,top);
        printf("%.0f\n",RotateCalipers(ans,top));
    }
}

圆与多边形交

int sgn(double x)
{
    if(fabs(x) < eps) return 0;
    if(x < 0) return -1;
    else return 1;
}
struct Point
{
    double x,y;
    Point(){}
    Point(double _x,double _y)
    {
        x = _x;
        y = _y;
    }
    void input()
    {
        scanf("%lf %lf",&x,&y);
    }
    Point operator + (const Point &b) const
    {
        return Point(x + b.x,y + b.y);
    }
    Point operator - (const Point &b) const
    {
        return Point(x - b.x,y - b.y);
    }
    double operator ^ (const Point &b) const
    {
        return x * b.y - y * b.x;
    }
    double operator * (const Point &b) const
    {
        return x * b.x + y * b.y;
    }
    Point operator * (const double &k) const
    {
        return Point(x * k, y * k);
    }
    double distance(Point p)
    {
        return hypot(x - p.x,y - p.y);
    }
    double rad(Point a,Point b)
    {
        Point p = *this;
        return fabs(atan2( fabs((a - p) ^ (b - p)),(a - p) * (b - p) ) );
    }
    Point operator / (const double &k) const
    {
        return Point(x / k, y / k);
    }
    double len()
    {
        return hypot(x,y);
    }
    double len2()
    {
        return x * x + y * y;
    }
    Point trunc(double r)
    {
        double l = len();
        if(!sgn(l)) return *this;
        r /= l;
        return Point(x * r,y * r);
    }
};
struct Line
{
    Point s,e;
    Line(){}
    Line(Point _s,Point _e)
    {
        s = _s;
        e = _e;
    }
    double length()
    {
        return s.distance(e);
    }
    double dispointtoline(Point p)
    {
        return fabs( (p - s) ^ (e - s)) / length();
    }
    Point lineprog(Point p)
    {
        return s + ( ((e - s) * ((e - s) * (p - s))) / ((e - s).len2()) );
    }
};
struct circle
{
    Point p;
    double r;
    circle(){}
    circle(double x,double y,double _r)
    {
        p = Point(x,y);
        r = _r;
    }
    int relation(Point b)
    {
        double dst = b.distance(p);
        if(sgn(dst - r) < 0) return 2;
        else if(sgn(dst - r) == 0) return 1;
        else return 0;
    }
    int relationline(Line v)
    {
        double dst = v.dispointtoline(p);
        if(sgn(dst - r) < 0) return 2;
        else if(sgn(dst - r) == 0) return 1;
        return 0;
    }
    int pointcrossline(Line v,Point &p1,Point &p2)
    {
        if(!(*this).relationline(v)) return 0;
        Point a = v.lineprog(p);
        double d = v.dispointtoline(p);
        d = sqrt(r * r - d * d);
        if(sgn(d) == 0) {
            p1 = a;
            p2 = a;
            return 1;
        }
        p1 = a + (v.e - v.s).trunc(d);
        p2 = a - (v.e - v.s).trunc(d);
        return 2;
    }
    double areatriangle(Point a,Point b)
    {
        if( sgn( (p - a) ^ (p - b)) == 0) return 0.0;
        Point q[5];
        int len = 0;
        q[len++] = a;
        Line l(a,b);
        Point p1,p2;
        if(pointcrossline(l,q[1],q[2]) == 2) {
            if(sgn((a - q[1]) * (b - q[1])) < 0) q[len++] = q[1];
            if(sgn((a - q[2]) * (b - q[2])) < 0) q[len++] = q[2];
        }
        q[len++] = b;
        if(len == 4 && sgn((q[0] - q[1]) * (q[2] - q[1])) > 0) swap(q[1],q[2]);
        double res = 0;
        for(int i = 0; i < len - 1; i++) {
            if(relation(q[i]) == 0 || relation(q[i + 1]) == 0) {
                double arg = p.rad(q[i],q[i + 1]);
                res += r * r * arg / 2.0;
            }
            else {
                res += fabs((q[i] - p) ^ (q[i + 1] - p)) / 2.0;
            }
        }
        return res;
    }
};
struct polygon
{
    int n;
    Point p[maxp];
    void input(int _n)
    {
        n = _n;
        for(int i = 0; i < n; i++) {
            p[i].input();
        }
    }
    double areacircle(circle c)
    {
        double ans = 0;
        for(int i = 0; i < n; i++) {
            int j = (i + 1) % n;
            if(sgn ( (p[j] - c.p ) ^ (p[i] - c.p ) ) >= 0)
                ans += c.areatriangle(p[i],p[j]);
            else ans -= c.areatriangle(p[i],p[j]);
        }
        return fabs(ans);
    }
};
int main(void)
{
    int n;
    double x0,y0,v0,angle,t,g,R,x1,y1;
    double sd,cd,sv,cv;
    while(cin >> x0 >> y0 >> v0 >> angle >> t >> g >> R) {
        if(x0 + y0 + v0 + angle + t + g + R == 0) break;
        angle = (angle * 2.0 * pi ) / 360.0;
        sv = v0 * cos(angle);
        cv = v0 * sin(angle);
        sd = sv * t;
        cd = cv * t - 0.5 * g * t * t;
        x1 = x0 + sd;
        y1 = y0 + cd;
        circle c(x1,y1,R);
        polygon pl;
        scanf("%d",&n);
        pl.input(n);
        printf("%.2lf\n",pl.areacircle(c));
    }
    return 0;
}
  • 1
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 1024 设计师:白松林 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值