Symmetry UVA - 1595

29 篇文章 0 订阅
5 篇文章 0 订阅

UVA-1595

题目:给出平面上的N(N<=1000)个点,问是否可以找到一条竖线,使得所有的点左右对称。

思路:先判断纵坐标(y值)相同的点,是否关于同一个直线x对称。最后在判断不同y值下的点是否关于同一个直线x对称。如果相同y下有奇数个点,则最中间的点的x值就必须为该y值下对称轴的x坐标。

        用map<int,vector<int>>来表示坐标轴y下的所有x值。记得先对y相同的点的x进行排序。中点x值用double。

#include <iostream>
#include <map>
#include <set>
#include <queue>
#include <string>
#include <sstream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <stack>
using namespace std;
int n,T,y[1000001],nun=0;
typedef vector<int> INT;
map<int,INT>dot;
const double MIN = 1e-6;
int check(double aim){
    for(int i = 1;i<=nun;i++){
        int p = 0,q = dot[y[i]].size()-1;
        while(p<=q){
            double x = (dot[y[i]][p]+dot[y[i]][q])/2.0;
            if(fabs(x-aim)>=MIN) return 0;
            p++;q--;
        }
    }
    return 1;
}
int main(){
    cin>>T;
    while(T--){
        int yes = 1,aim_i;
        double aim;
        nun = 0;
        dot.clear();
        cin>>n;
        for(int i = 1;i<=n;i++){
            int a,b;
            cin>>a>>b;
            if(!dot.count(b)){dot[b].push_back(a);y[++nun]=b;} //y[]来保存y值
            else dot[b].push_back(a);
        }
        for(int i = 1;i<=nun;i++) sort(dot[y[i]].begin(),dot[y[i]].end());//对y相同的点根据x值排序
        for(int i = 1;i<=nun;i++){
            if(dot[y[i]].size()%2==0){
                aim = (dot[y[i]][0]+dot[y[i]][dot[y[i]].size()-1])/2.0;  //取出一个对称轴的x值,看其是否为其他点的对称轴
                if(!check(aim)){
                    yes = 0;
                    break;
                }
            }
            if(dot[y[i]].size()%2==1){
                aim_i = (dot[y[i]].size()+1)/2-1; 
                aim = dot[y[i]][aim_i]; //取出一个中点的x值,看其是否为其他点的对称轴
                if(!check(aim)){
                    yes = 0;
                    break;
                }
            }
        }
        if(yes) cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值