https://vjudge.net/problem/UVA-1595
之前没做过这种题目,一时间没想出来如何下手。
想通之后,剩下的操作只剩下排序了。
对于任意n个散点,一旦给出,他们的对称轴实际上已经确定了,而且十分好求:
横对称轴 一定是 横坐标最大的X1和横坐标最小的 X2 的平均数,即 X0 = 1/2(X1 + X2)
这个结论可以用反证法推出,画图十分好理解,证明就不赘述了。
下面问题是:找出了对称轴,如何将所有的点对应出来?
很自然的考虑到将所有的点按照与对称轴的位置关系分类:
< 1 > 如果这个点恰好在对称轴上,那么它一定对称(和自己对称),可以直接丢掉了。
< 2 > 如果在轴的左右两边:分别存在两个数组中,以后方便对应检验。
这个操作用for循环遍历很好实现。注意对称轴有可能是浮点数,因此要用double来表示。如果用int会误判
好了,现在已经将所有的点按两侧分开了,还需要解决什么呢?
两个数组的size是否相等? 这是最基本的一个条件,如果左右两边的点数都不同,那必然不对称,不需要进一步检验了,直接continue就好了(不是break...我一开始错在这里...)
如果size相同继续往后走:
还有两个要素:
< 1 > 离对称轴的距离多远?
< 2 > 高度 y 有多大?
处理这两个要素,其实很简单: 设计一个comp函数,进行多级排序即可。然后用两个迭代器同步遍历数组检查即可。
应该讲的比较清楚了。代码中就不写注释了。
AC代码: 10 ms
1 #include2 #include 3 #include 4 #include 5 #define INF 0x3fffffff 6 using namespace std; 7 struct node{ 8 int x; 9 int y; 10 double diff; 11 }; 12 double SymmetricX; 13 bool Equal(double m,double n){ 14 return fabs(m-n)<1e-6; 15 } 16 bool comp(const node&a,const node&b){ 17 if(not Equal(a.diff,b.diff))return a.diff < b.diff; 18 else return a.y < b.y; 19 } 20 int main(){ 21 int tests; 22 cin >> tests; 23 while(tests--){ 24 int num; 25 cin >> num; 26 vector arr(1001); 27 int find_max = -INF,max_point = -1; 28 int find_min = INF,min_point = -1; 29 for(int i = 0; i < num; i++){ 30 cin >> arr[i].x >> arr[i].y; 31 if(arr[i].x < find_min){ 32 find_min = arr[i].x; 33 min_point = i; 34 } 35 if(arr[i].x > find_max){ 36 find_max = arr[i].x; 37 max_point = i; 38 } 39 } 40 SymmetricX = (find_max + find_min)*1.0/2; 41 vector lr[2]; 42 for(int i = 0; i < num; i++){ 43 double diff = arr[i].x - SymmetricX; 44 if(Equal(diff,0))continue; 45 arr[i].diff = fabs(diff); 46 if(diff < 0)lr[0].push_back(arr[i]); 47 else lr[1].push_back(arr[i]); 48 } 49 if(lr[0].size() not_eq lr[1].size()){ 50 cout<<"NO"<<endl; 51 continue; 52 } 53 sort(lr[0].begin(), lr[0].end(), comp); 54 sort(lr[1].begin(), lr[1].end(), comp); 55 vector :: iterator it = lr[0].begin(); 56 vector :: iterator it2 = lr[1].begin(); 57 int flag = 0; 58 while(it not_eq lr[0].end() and it2 not_eq lr[1].end()){ 59 if(it->y not_eq it2->y){ 60 flag = 1; 61 break; 62 } 63 it++; it2++; 64 } 65 if(flag)cout<<"NO"<<endl; 66 else cout<<"YES"<<endl; 67 } 68 return 0; 69 }