A - Axis of Symmetry 2019-2020 ICPC Asia Hong Kong Regional Contest

看着没人发代码,我扔下我的吧
我的思路大概就是用一个大的矩形把所有的矩形的围住,然后用四条对称轴去切,判断一个点与对称轴对称的点是否也存在,不存在则不能通过这条对称轴切

在这里插入图片描述
红色的为对称轴

#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(int i=(int)(a);i<=(int)(b);i++)
const long long MOD = 1e9 + 7;
const int MAXN = 5e5 + 9;
const int INF = 0x3f3f3f3f;
const double EPS=1e-6;
inline int sgn(double x){
    if(x<-EPS)return -1;
    return x>EPS;
}
inline int cmp(double x,double y){
    return sgn(x-y);
}
long long n,m;
int tot;
struct Point{
    double x,y;
    void read(){
        scanf("%lf%lf",&x,&y);
    }
    bool operator<(const Point p)const{
        if(cmp(x,p.x)==0)return y<p.y;
        return x<p.x;
    }
    bool operator==(const Point p)const{
        return cmp(x,p.x)==0&&cmp(y,p.y)==0;
    }
    Point operator-(const Point p)const{
        return (Point){x-p.x,y-p.y};
    }
    Point operator+(const Point p)const{
        return (Point){x+p.x,y+p.y};
    }
    double len2(){
        return x*x+y*y;
    }
    double operator*(const Point p)const{
        return x*p.x+y*p.y;
    }
    Point operator*(const double d)const{
        return (Point){x*d,y*d};
    }
    Point operator/(const double d)const{
        return (Point){x/d,y/d};
    }
}p[MAXN];
struct Ans{
    double a,b,c;
    bool operator<(const Ans s)const{
        if(a>s.a)return true;
        if(a<s.a)return false;
        if(b>s.b)return true;
        if(b<s.b)return false;
        return c>s.c;
    }
}ans[5];
struct Line{
    Point s,e;
    Point lineProg(Point p){//checked
        //`返回点p在直线上的投影`
        return s + ( ((e-s)*((e-s)*(p-s)))/((e-s).len2()) );
    }
    Point symmetryPoint(Point p){
        //`返回点p关于直线的对称点`
        Point q = lineProg(p);
        return (Point){2*q.x-p.x,2*q.y-p.y};
    }
};
int now;
bool check(Line line){
    rep(i,1,now){//查找所有点的对称点是否在数组里
        int l=1,r=now;
        bool flag=false;
        Point point=line.symmetryPoint(p[i]);
        while(l<r-3){//二分查找是否存在
            int mid=(l+r)/2;
            if(point==p[mid]){
                flag=true;
                break;
            }
            if(p[mid]<point)l=mid;
            else r=mid;
        }
        if(flag)continue;
        rep(j,l,r){
            if(p[j]==point){
                flag=true;
                break;
            }
        }
        if(!flag)return false;
    }
    return true;
}
void solve(){
    sort(p+1,p+1+4*n);
    now=0;
    int l=1;
    while(l<=4*n){
        if(l+1<=4*n){
            int r=l+1;
            while(r<=4*n&&p[r]==p[l])r++;
            if(r==l+1){
                p[++now]=p[l];
            }
            l=r;
        }else{
            p[++now]=p[l++];
        }
    }
    double mxx=p[1].x,mnx=p[1].x,mxy=p[1].y,mny=p[1].y;
    rep(i,1,now){
        mxx=max(mxx,p[i].x);
        mnx=min(mnx,p[i].x);
        mxy=max(mxy,p[i].y);
        mny=min(mny,p[i].y);
    }
    double a,b,c;
    int num=0;
    Point leftdown={mnx,mny};
    Point leftup={mnx,mxy};
    Point rightdown={mxx,mny};
    Point rightup={mxx,mxy};

    a=0,b=2,c=mxy+mny;
    Line line;
    line={{0,c/2},{1,c/2}};
    if(check(line)){
        long long cc=c;
        if(cc%2==0){
            b/=2;c/=2;
        }
        ans[++num]={a,b,c};
    }

    a=2,b=0,c=mxx+mnx;
    line={{c/2,0},{c/2,1}};
    if(check(line)){
        long long cc=c;
        if(cc%2==0){
            a/=2;c/=2;
        }
        ans[++num]={a,b,c};
    }

    if(cmp(mxy-mny,mxx-mnx)==0){
        a=1,b=-1,c=mnx-mny;
        line={leftdown,rightup};
        if(check(line)){
            ans[++num]={a,b,c};
        }

        a=1,b=1,c=mnx+mxy;
        line={leftup,rightdown};
        if(check(line)){
            ans[++num]={a,b,c};
        }
    }
    printf("%d\n",num);
    sort(ans+1,ans+1+num);
    rep(i,1,num){
        printf("%.0f %.0f %.0f ",ans[i].a,ans[i].b,ans[i].c);
    }
    printf("\n");
}
void init(){
    scanf("%d",&n);
    rep(i,1,n){
        p[i*4-3].read();
        p[i*4-2].read();
        p[i*4-1]=(Point){p[i*4-3].x,p[i*4-2].y};
        p[i*4-0]=(Point){p[i*4-2].x,p[i*4-3].y};
    }
}
int main() {
    int T;
//    freopen("data.in","r",stdin);
    scanf("%d",&T);
    while(T--){
        init();
        solve();
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值