题目:给出平面上的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;
}
}