bzoj2592 Symmetry

229 篇文章 0 订阅

对于每条对称轴,某个点有两种情况:要不然在对称轴上,要不然在对称轴一侧。不妨依此进行分类讨论。
考虑 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);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值