CSU 1896: Symmetry(对称点集)

来源:互联网 发布:python 多线程 返回值 编辑:程序博客网 时间:2024/06/05 20:06

题目:

Description

We call a figure made of points is left-right symmetric as it is possible to fold the sheet of paper along a vertical line and to cut the figure into two identical halves.For example, if a figure exists five points, which respectively are (-2,5),(0,0),(2,3),(4,0),(6,5). Then we can find a vertical line x = 2 to satisfy this condition. But in another figure which are (0,0),(2,0),(2,2),(4,2), we can not find a vertical line to make this figure left-right symmetric.Write a program that determines whether a figure, drawn with dots, is left-right symmetric or not. The dots are all distinct.

Input

The input consists of T test cases. The number of test cases T is given in the first line of the input file. The first line of each test case contains an integer N, where N (1 <=N <= 1, 000) is the number of dots in a figure. Each of the following N lines contains the x-coordinate and y-coordinate of a dot. Both x-coordinates and y-coordinates are integers between −10, 000 and 10, 000, both inclusive.

Output

Print exactly one line for each test case. The line should contain 'YES' if the figure is left-right symmetric,and 'NO', otherwise.

Sample Input

35-2 50 06 54 02 342 30 44 00 045 146 105 106 14

Sample Output

YESNOYES

这个题目是说,给一个整点集,判断是不是左右对称的。

要分2步进行,第一步找到唯一可能的对称轴的位置,第二步是判断点集是不是关于这条直线对称的。

第一步我是找最中间的若干个点,第二步我是把所有不在对称轴上面的点映射到一个整数,使得对称的点映射到一样的整数,不对称的点几乎不会映射到一样的整数,最后求出所有整数的异或,是0就对称,不是0就不对称。

我在比赛时提交的代码:

#include<iostream>#include<algorithm>using namespace std;int kx1,kx2;struct node{int x,y;};bool cmp(node n1,node n2){return n1.x<n2.x;}int f(node nodd,int kx){if(nodd.x*2<kx)return (kx-nodd.x*2)%123*nodd.y;return (nodd.x*2-kx)%123*nodd.y;}int main(){int T,N,ans1,ans2;node nod[1000];cin>>T;while(T--){cin>>N;for(int i=0;i<N;i++)cin>>nod[i].x>>nod[i].y;sort(nod,nod+N,cmp);kx1=nod[N/2].x*2;kx2=nod[N/2].x+nod[(N-1)/2].x;ans1=ans2=0;for(int i=0;i<N;i++){ans2=ans2^f(nod[i],kx2);if(nod[i].x==kx1)continue;ans1=ans1^f(nod[i],kx1);}if(ans1==0||ans2==0)cout<<"YES\n";else cout<<"NO\n";}return 0;}

实际上求对称轴还有更好的方法,不用最中间的点,用最左边和最右边的点。

第二步也不需要映射到整数,直接把点集存2份,一份从左往右排序,一份从右往左排序,然后一一比较是否对称即可。

新代码:

#include<iostream>#include<algorithm>using namespace std;int T, N, kx;struct node{int x, y;};node nod1[1000], nod2[1000];bool cmp1(node n1, node n2){if (n1.x == n2.x)return n1.y < n2.y;return n1.x<n2.x;}bool cmp2(node n1, node n2){if (n1.x == n2.x)return n1.y < n2.y;return n1.x>n2.x;}bool ok(){for (int i = 0; i < N; i++){if (nod1[i].y != nod2[i].y)return false;if (nod1[i].x + nod2[i].x != kx)return false;}return true;}int main(){int left, right;cin >> T;while (T--){cin >> N;left = 10000, right = -10000;for (int i = 0; i < N; i++){cin >> nod1[i].x >> nod1[i].y;nod2[i].x = nod1[i].x, nod2[i].y = nod1[i].y;if (left>nod1[i].x)left = nod1[i].x;if (right < nod1[i].x)right = nod1[i].x;}kx = left + right;sort(nod1, nod1 + N, cmp1);sort(nod2, nod2 + N, cmp2);if (ok())cout << "YES\n";else cout << "NO\n";}return 0;}

0 0
原创粉丝点击