gym 101623 G .Glyph Recognition

二分两个多边形大小。附上一堆板子

#include<bits/stdc++.h>
#define mp make_pair
#define fir first
#define sec second
using namespace std;
typedef long long ll;
const double eps = 1e-12;
const double PI = acos(-1.0);
const int MX = 1e5+7;

struct Point {
    double x, y;
    void read(){
        scanf("%lf%lf",&x,&y);
    }
    void print(){
        printf("%.10f %.10f\n",x,y);
    }
    Point() {}
    Point(double x,double y):x(x),y(y) {}
}q[MX];
typedef Point Vector;

int dcmp(double x) { //返回x的正负
    if(fabs(x)<eps)return 0;
    return x<0?-1:1;
}

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);}
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;//如果改成整形记得加LL
}
double Cross(Vector A,Vector B) { //叉积
    return A.x*B.y-A.y*B.x;//如果改成整形记得加LL
}
//向量长度
double Length(Vector A) {
    return sqrt(Dot(A,A));
}
//2个向量之间的夹角
double Angle(Vector A,Vector B) {
    return acos(Dot(A,B)/Length(A)/Length(B));
}
//向量的极角
double angle(Vector v) {
    return atan2(v.y,v.x);
}
//计算ABC的有向面积
double Area(Point A,Point B,Point C) {
    return Cross(B-A,C-A)/2;
}
//将A向量逆时针旋转rad
Vector Rotate( Vector A,double rad) {
    return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));
}

bool OnSegment(Point p,Point a1,Point a2) {
    return dcmp(Cross(a1-p,a2-p))==0&&dcmp(Dot(a1-p,a2-p))<0;
}
int IsPointInPolygon(Point p, Point *R,int n){
    int wn = 0;
    for(int i = 0; i < n; i++){
        const Point& p1 = R[i];
        const Point& p2 = R[(i+1)%n];
        if(p1 == p || p2 == p || OnSegment(p, p1, p2)) return -1; // 在边界上
        int k = dcmp(Cross(p2-p1, p-p1));
        if(k > 0) wn++;
        if(k < 0) wn--;
    }
    if (wn == n) return 1; // 内部
    return 0; // 外部
}

double PolygonArea(Point *p,int n) {
    double area=0;
    p[n] = p[0];
    for(int i=1; i<n-1; i++)
        area+=Cross(p[i]-p[0],p[i+1]-p[0]);
    return fabs(area/2);
}

int ansx = 3;
double ans;
void get_p(Point *p, double r, int sz)
{
    Vector v = Vector(r,0);
    for(int i = 0; i < sz; i++){
        p[i] = Rotate(v,PI*2*(i+1)/sz);
    }
}

bool check1(Point *p, double r, int sz, int n)
{
    get_p(p,r,sz);

    for(int i = 0; i < n; i++){
        int tmp = IsPointInPolygon(q[i],p,sz);
        if(tmp == 0) return 0;
    }
    return 1;
}

bool check2(Point *p, double r, int sz, int n)
{
    get_p(p,r,sz);
    for(int i = 0; i < n; i++){
        int tmp = IsPointInPolygon(q[i],p,sz);
        if(tmp == 1) return 0;
    }
    return 1;
}

void work(int x, int n)
{
    double rout = 0, rin = 0;;
    double l = 0, r = 4000000;
    Point p1[11],p2[11];

    int cnt = 200;
    while(cnt--){
        double mid = (l+r)/2;
        if(check1(p1,mid,x,n)) r = mid;
        else l = mid;
    }
    rout = l;

    l = 0, r = 4000000;
    cnt = 200;
    while(cnt--){
        double mid = (l+r)/2;
        if(check2(p2,mid,x,n)) l = mid;
        else r = mid;
    }
    rin = l;

    double t = PolygonArea(p2,x)/ PolygonArea(p1,x);
    if(t > ans){
        ans = t;
        ansx = x;
    }
}

int main()
{
#ifdef LOCAL
    freopen("input.txt","r",stdin);
#endif // LOCAL
    int n;
    scanf("%d",&n);
    for(int i = 0; i < n; i++)
        q[i].read();
    for(int i = 3; i <= 8; i++)
        work(i,n);
    printf("%d %.8f\n",ansx,ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_18869763/article/details/83551942
今日推荐