bzoj2592: [Usaco2012 Feb]Symmetry

Description

After taking a modern art class, Farmer John has become interested in finding geometric patterns in everything around his farm. He carefully plots the locations of his N cows (2 <= N <= 1000), each one occupying a distinct point in the 2D plane, and he wonders how many different lines of symmetry exist for this set of points. A line of symmetry, of course, is a line across which the points on both sides are mirror images of each-other. Please help FJ answer this most pressing geometric question.

上过现代艺术课后,FJ开始感兴趣于在他农场中的几何图样。他计划将奶牛放置在二维平面上的N个互不相同的点(1<=N<=1000),他希望找出这个点集有多少条对称轴。他急切地需要你帮忙解决这个几何问题。

Input

* Line 1: The single integer N.

* Lines 2..1+N: Line i+1 contains two space-separated integers representing the x and y coordinates of the ith cow (-10,000 <= x,y <= 10,000).

Output

* Line 1: The number of different lines of symmetry of the point set.

圆上的整点很少,所以可以找出点集的重心并把点按到重心的距离排序,到重心相同距离的点在同一圆上,计算这些点的对称轴(最多四条),最后取交集即可,时间复杂度是O(n2logn)但因为整点且范围小所以不会达到最坏情况

#include<bits/stdc++.h>
typedef long double ld;
const ld pi=std::acos(-1),_0=1e-7l;
int n,ans=0,xs=0,ys=0,lp=0,ap=0,ad=0;
struct pos{int x,y;long long d;ld a;}ps[1007];
ld ls[2007],as[2007];
bool operator<(pos a,pos b){
    return a.d!=b.d?a.d<b.d:a.a<b.a;
}
ld dis(ld x,ld y){
    return std::sqrt(x*x+y*y);
}
int fix(int a,int l,int r){
    if(a<l)return a+r-l;
    if(a>=r)return a-r+l;
    return a;
}
bool feq(ld a,ld b){
    return fabs(a-b)<_0;
}
bool chk(ld x){
    while(x>pi*2-_0)x-=pi*2;
    while(x<_0-pi*2)x+=pi*2;
    return std::fabs(x)<_0;
}
int main(){
    scanf("%d",&n);
    for(int i=0;i<n;i++)scanf("%d%d",&ps[i].x,&ps[i].y);
    for(int i=0;i<n;i++){
        xs+=ps[i].x;
        ys+=ps[i].y;
    }
    for(int i=0;i<n;i++){
        (ps[i].x*=n)-=xs;
        (ps[i].y*=n)-=ys;
        ps[i].d=1ll*ps[i].x*ps[i].x+1ll*ps[i].y*ps[i].y;
        ps[i].a=atan2(ps[i].y,ps[i].x);
    }
    std::sort(ps,ps+n);
    int p0=0,p1;
    while(ps[p0].x==0&&ps[p0].y==0)++p0;
    for(p1=p0;p0<n;p0=p1){
        while(p1<n&&ps[p1].d==ps[p0].d)++p1;
        lp=0;
        for(int p2=p0;p2<p1;p2++){
            bool ab=1;
            ld m=ps[p2].a*2;
            for(int l=fix(p2-1,p0,p1),r=fix(p2+1,p0,p1);;l=fix(l-1,p0,p1),r=fix(r+1,p0,p1)){
                if(!chk(ps[l].a+ps[r].a-m)){
                    ab=0;
                    break;
                }
                if(l==r)break;
            }
            if(ab==1)ls[lp++]=ps[p2].a;
            if(p1-p0&1)continue;
            ab=1;
            m=(ps[p2].a+ps[fix(p2+1,p0,p1)].a);
            for(int l=fix(p2,p0,p1),r=fix(p2+1,p0,p1),t=p1-p0>>1;t;--t,l=fix(l-1,p0,p1),r=fix(r+1,p0,p1)){
                if(!chk(ps[l].a+ps[r].a-m)){
                    ab=0;
                    break;
                }
                if(l==r)break;
            }
            if(ab)ls[lp++]=m/2.;
        }
        for(int i=0;i<lp;i++){
            ld x=ls[i];
            while(x<-_0)x+=pi;
            while(x>pi-_0)x-=pi;
            ls[i]=x;
        }
        std::sort(ls,ls+lp);
        lp=std::unique(ls,ls+lp,feq)-ls;
        if(ad){
            int lp1=0,ap1=0;
            for(int i=0;i<ap;i++){
                while(lp1<lp&&ls[lp1]<as[i]-_0)++lp1;
                if(lp1==lp)break;
                if(feq(as[i],ls[lp1]))as[ap1++]=as[i];
            }
            ap=ap1;
        }else{
            ad=1;
            for(int i=0;i<lp;i++)as[ap++]=ls[i];
        }
    }
    printf("%d",ap);
    return 0;
}
时间: 2024-10-24 16:04:42

bzoj2592: [Usaco2012 Feb]Symmetry的相关文章

BZOJ2590: [Usaco2012 Feb]Cow Coupons

n<=50000组数Ai,Bi,Ai>=Bi,最多K<=n个组选Bi,其他组选Ai,求最多能选中几组数使选数总和不超过M<=1e14. 一开始,肯定是在Bi里面选K个最小的,然后M有剩的再来调整.如何调整呢?现在我有两个选择:在没选的数里面选个最小的Aj,否则在选的K个最小Bi的里面,把某个Bi换成Ai,多出一次机会拿没选的数字中最小的一个Bj.前者可以开个堆或排个序,后者其实是要找Ai-Bi+Bj的最小,开两个堆分别维护Ai-Bi的最小和Bj的最小即可. 第一次WA:Bj选中后忘

BZOJ 1592: [Usaco2008 Feb]Making the Grade 路面修整( dp )

最优的做法最后路面的高度一定是原来某一路面的高度. dp(x, t) = min{ dp(x - 1, k) } + | H[x] - h(t) | ( 1 <= k <= t ) 表示前 i 个路面单调不递减, 第 x 个路面修整为原来的第 t 高的高度. 时间复杂度O( n³ ). 令g(x, t) = min{ dp(x, k) } (1 <= k <= t), 则转移O(1), g() 只需在dp过程中O(1)递推即可, 总时间复杂度为O( n² ) 然后单调不递增也跑一遍

bzoj3943[Usaco2015 Feb]SuperBull*

bzoj3943[Usaco2015 Feb]SuperBull 题意: n头牛进行锦标赛,每场比赛的好看程度是两头牛的编号异或和,并总有一方被淘汰.求安排比赛(可以决定比赛胜负)可以得到的最大总好看程度是多少.n≤2000 题解: 先求出牛两两之间的异或和,然后发现可以把比赛看做连边,且共有n-1场比赛,所以求最大生成树就行了.神犇们用的都是Prim,蒟蒻不会,用Kruscal结果时间排倒数. 代码: 1 #include <cstdio> 2 #include <cstring>

bzoj3942: [Usaco2015 Feb]Censoring

AC自动机.嗯bzoj3940弱化版.水过去了(跑的慢啊QAQ.想了想可以用hash写.挖坑 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<queue> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define clr(x,c) memset

BZOJ 3011: [Usaco2012 Dec]Running Away From the Barn( dfs序 + 主席树 )

子树操作, dfs序即可.然后计算<=L就直接在可持久化线段树上查询 ------------------------------------------------------------------- #include<bits/stdc++.h> using namespace std; #define M(l, r) (((l) + (r)) >> 1) const int maxn = 200009; typedef long long ll; inline ll

1611: [Usaco2008 Feb]Meteor Shower流星雨

1611: [Usaco2008 Feb]Meteor Shower流星雨 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1010  Solved: 446[Submit][Status][Discuss] Description 去年偶们湖南遭受N年不遇到冰冻灾害,现在芙蓉哥哥则听说另一个骇人听闻的消息: 一场流星雨即将袭击整个霸中,由于流星体积过大,它们无法在撞击到地面前燃烧殆尽, 届时将会对它撞到的一切东西造成毁灭性的打击.很自然地,芙蓉哥哥开

2620: [Usaco2012 Mar]Haybale Restacking

2620: [Usaco2012 Mar]Haybale Restacking Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 201  Solved: 111[Submit][Status][Discuss] Description Farmer John has just ordered a large number of bales of hay. He would like to organize these into N piles (1

BZOJ 1633: [Usaco2007 Feb]The Cow Lexicon 牛的词典

题目 1633: [Usaco2007 Feb]The Cow Lexicon 牛的词典 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 401  Solved: 216[Submit][Status] Description 没有几个人知道,奶牛有她们自己的字典,里面的有W (1 ≤ W ≤ 600)个词,每个词的长度不超过25,且由小写字母组成.她们在交流时,由于各种原因,用词总是不那么准确.比如,贝茜听到有人对她说"browndcodw"

Fast Radial Symmetry Transform/快速径向对称变换

本文主要介绍一下利用径向变换进行特征提取的方法和原理,基本原理主要来自Gareth Loy and Alexander Zelinsky的A Fast Radial Symmetry Transform for Detecting Points of Interest一文.需要原文的可以留下邮箱. Radial Symmetry Transform(径向对称变换)在某种程度上类似于霍夫圆变换,二者的主要区别在于:前者主要考察一副图像中的每个像素点对它周围邻域内的像素点的作用(贡献),而后者则主要