• Ural 1043 Cover the Arc


    题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1043

    题目大意:一个2000*2000方格坐标,x,y范围都是【-1000,1000】。现在给你一个圆弧,告诉你圆弧的两个端点和任意一个中间点。现在要你算出最小的矩形(长和宽都要为整数,即四个顶点在方格顶点上)来完全覆盖这个圆弧。

     算法思路:很明显要算出圆心,这个可以有线段中垂线交求,也可以由方程,只是很麻烦。然后以圆心找出这个圆的左右上下四个极点,判断是否在圆弧上(用叉积即可),与给出的三个点一起维护这段圆弧的四个方向的极大点。然后向上向下取整即可。

    代码:

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    using namespace std;
    
    const double eps = 1e-3;
    const double INF = 1000000000.00;
    
    struct Point{
        double x,y;
        Point(double x=0,double y=0): x(x), y(y) {}
    };
    
    typedef Point Vector;
    
    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); }
    
    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;
        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;
    }
    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; }
    
    
    Point read_point()
    {
        Point P;
        scanf("%lf %lf",&P.x,&P.y);
        return P;
    }
    Point normal(Vector A) { return Vector(-A.y,A.x); };
    
    Point GetLineIntersecion(Point P, Vector v,Point Q,Vector w){
        Vector u = P - Q;
        double t = Cross(w,u)/Cross(v,w);
        return P + v*t;
    }
    
    void Judge(Point& Pl,Point& Pr,Point& Pu,Point& Pd,Point P){
        if(Pl.x > P.x) Pl = P;
        if(Pr.x < P.x) Pr = P;
        if(Pu.y < P.y) Pu = P;
        if(Pd.y > P.y) Pd = P;
    }
    
    int main()
    {
        //freopen("E:\acm\input.txt","r",stdin);
        Point Ps,Pt,Pi;
        Ps = read_point();
        Pt = read_point();
        Pi = read_point();
        Point mid1,mid2,O;
    
        mid1 = (Ps+Pi)/2;
        mid2 = (Pi+Pt)/2;
        O = GetLineIntersecion(mid1,normal(Ps-Pi),mid2,normal(Pi-Pt));
    
        double r = Length(O-Ps); 
        Point Pu,Pl,Pr,Pd;
        Pu = Pl = Pr = Pd = Ps;
    
        Judge(Pl,Pr,Pu,Pd,Pt);
        Judge(Pl,Pr,Pu,Pd,Pi);
    
        Point P = Point(O.x+r,O.y);
        if(dcmp(Cross(Pt-Ps,Pi-Ps)*Cross(Pt-Ps,P-Ps)) > 0){
            Judge(Pl,Pr,Pu,Pd,P);
        }
        P = Point(O.x-r,O.y);
        if(dcmp(Cross(Pt-Ps,Pi-Ps)*Cross(Pt-Ps,P-Ps)) > 0){
            Judge(Pl,Pr,Pu,Pd,P);
        }
        P = Point(O.x,O.y+r);
        if(dcmp(Cross(Pt-Ps,Pi-Ps)*Cross(Pt-Ps,P-Ps)) > 0){
            Judge(Pl,Pr,Pu,Pd,P);
        }
        P = Point(O.x,O.y-r);
        if(dcmp(Cross(Pt-Ps,Pi-Ps)*Cross(Pt-Ps,P-Ps)) > 0){
            Judge(Pl,Pr,Pu,Pd,P);
        }
        int width = ceil(Pu.y-eps) - floor(Pd.y+eps); 
        int length = ceil(Pr.x-eps) - floor(Pl.x+eps);
        printf("%d
    ",width*length);
    }
    View Code
  • 相关阅读:
    Java基础
    数据库表设计
    Spring循环依赖
    Mysql类型转换
    Mysql刷题
    JavaScript
    Git
    告别.NET生成报表统计图的烦恼
    JS给页面标签添加事件(或超链接链接)
    发现联想手机P630型号的一个严重的系统Bug
  • 原文地址:https://www.cnblogs.com/acmdeweilai/p/3337386.html
Copyright © 2020-2023  润新知