UVa 1595 Symmetry (set && math)

题意:给出n个在直角坐标系上的点,问你能不能找出一条竖轴(即垂直于x的轴)使得所有的点根据这条轴对称,能则输出YES,否则输出NO

 

分析:首先需要找到对称轴的值,将所有n个点的x轴的值加起来然后去除以n便可得(证明在下方)。对于各个点的处理就是将每一个点的x,y组成一个pair丢到set里面去让其自动根据x轴的大小来排序,然后遍历一遍set,根据对称轴信息就可以得到对称点,如果有对称点不在set里面那就是NO的情况,否则反之! 但是在偶数个点的时候,对称轴的值会出现小数点,涉及到精度问题,那有没有办法来避免这个问题呢?实际上是有的,先说结论:2*sum = |x1|*n + |x2|*n (sum是所有点x轴的值的和,x1和x2是对称点,n是点的个数),有了这个,便能很快根据已知点找到对称点了!以下给出证明(参考自:http://blog.csdn.net/bryant_hao/article/details/51914988 )

 

公式证明:   首先,我先假设一个平面上有n个点。 
       并且假设这n个点都是对称的。(x1,x2,x3,x4,x5……xn) 
       就是平面上有一个对称轴,比如所有左边的点关于这个对称轴对称之后都可以在右边找到一个相对应的点。 
       那么求对称轴的横坐标呢就是(x1+xn)/2+(x2+x(n-1))/2……; 
       假如恰好是偶数个点,则对称轴的横坐标就是全部加起来除以点的个数了。 
       如果是奇数,则对称轴上肯定有一个点。 对称轴的横坐标我们还是可以加起来除以点的个数的: 
       (x1+xn)/2=(x1+xi+xn)/3 
       xi=(x1+xn)/2 
       同理:(x1+xn+x2+x(n-1))/4=(x1+x2+xn+x(n-1)+xi)/5 
       则奇数偶数统计起来一起考虑就是:对称轴的横坐标其实就是所有的点加起来除以所有点的个数; 
       sum*2-x1得到的是对称轴另一边的点的横坐标x2,这个地方也需要证明一下。 
       sum呢就是把所有点的横坐标都加起来了,其实这个时候sum就是对称点的横坐标放大n被之后的对称轴的横坐标。 
       由于两点到对称轴横坐标的距离是相等的 
       则可以得出式子: 
       sum-|x1|=xn-sum; 
       2*sum=xn+|x1|; 

#include<bits/stdc++.h>
using namespace std;
set< pair<int, int> > s;
int main(void)
{
    int nCase;
    scanf("%d",&nCase);
    while(nCase--){
        int n;
        s.clear();
        scanf("%d",&n);
        int sum = 0;
        for(int i=0; i<n; i++){
            int x, y;
            scanf("%d%d",&x, &y);
            sum+=x;
            s.insert(make_pair(x*n, y));
        }
        bool flag = true;
        for(set< pair<int, int> >::iterator it=s.begin(); it!=s.end(); it++){
            if(!s.count(make_pair(2*sum - (*it).first, (*it).second))){
                flag = false;
                break;
            }
        }
        if(flag) puts("YES");
        else puts("NO");
    }
    return 0;
}
View Code

 

posted @ 2017-05-19 16:50  qwerity  阅读(174)  评论(0编辑  收藏  举报