bzoj2592 Symmetry

来源:互联网 发布:yii2连接oracle数据库 编辑:程序博客网 时间:2024/05/16 14:08

对于每条对称轴,某个点有两种情况:要不然在对称轴上,要不然在对称轴一侧。不妨依此进行分类讨论。
考虑1号点,如果它不在对称轴上直接枚举它的对称点。如果它在对称轴上,考虑2号点。如果它也在对称轴上,这条对称轴就确定了。否则我们枚举2号点的对称点,注意这时候得到的对称轴要满足1号点在对称轴上。

#include<cstdio>#include<algorithm>#include<cmath>#include<set>using namespace std;const double eps=1e-8;const int maxn=1010,p=131,mod=1000007;int cmp(double x){    if (x>eps) return 1;    if (fabs(x)<=eps) return 0;    return -1;}struct Vector{    double x,y;    void rd()    {        scanf("%lf%lf",&x,&y);    }    bool operator < (const Vector &v) const    {        int c=cmp(x-v.x);        if (c==0) return cmp(y-v.y)==-1;        return c==-1;    }    Vector operator + (const Vector &v) const    {        return (Vector){x+v.x,y+v.y};    }    Vector operator - (const Vector &v) const    {        return (Vector){x-v.x,y-v.y};    }    Vector operator * (const double &k) const    {        return (Vector){x*k,y*k};    }    Vector operator / (const double &k) const    {        return (Vector){x/k,y/k};    }}a[maxn];typedef Vector Point;double dot(Vector v,Vector u){    return v.x*u.x+v.y*u.y;}double cross(Vector v,Vector u){    return v.x*u.y-v.y*u.x;}double len(Vector v){    return sqrt(dot(v,v));}Point midpoint(Point p,Point q){    return (p+q)/2;}Vector normal(Vector v){    return (Vector){-v.y,v.x};}struct Line{    Point p;    Vector v;};bool online(Point p,Line l){    return cmp(cross(p-l.p,l.v))==0;}double dis(Point p,Line l){    return fabs(cross(p-l.p,l.v))/len(l.v);}Line perbi(Point p,Point q){    return (Line){midpoint(p,q),normal(p-q)};}Point symm(Point p,Line l){    Vector v=normal(l.v);    v=v/len(v);    v=v*(2*dis(p,l));    Point q1=p+v,q2=p-v;    if (cmp(dot(q1-p,l.p-p))==1) return q1;    return q2;}set<Vector> s;int n;int check(Line l){    for (int i=1;i<=n;i++)        if (!s.count(symm(a[i],l))) return 0;    return 1;}int main(){    //freopen("b.in","r",stdin);    Line l;    int ans=0;    scanf("%d",&n);    for (int i=1;i<=n;i++) a[i].rd(),s.insert(a[i]);    for (int i=2;i<=n;i++)        if (check(perbi(a[1],a[i]))) ans++;    if (check((Line){a[1],a[2]-a[1]})) ans++;    for (int i=3;i<=n;i++)    {        l=perbi(a[2],a[i]);        if (online(a[1],l)&&check(l)) ans++;    }    printf("%d\n",ans);}