首页 > ACM题库 > HDU-杭电 > HDU 4613-Points-计算几何-[解题报告]HOJ
2015
09-17

HDU 4613-Points-计算几何-[解题报告]HOJ

Points

问题描述 :

  A set of integer points on a plane (points whose both cartesian coordinates are integers) which we shall refer to as the pattern, as well as a group of other sets of integer points on the plane are given. We would like to know which of the sets are similar to the pattern, i.e. which of them can be transformed by rotations, translations, reflections and dilations so that they are identical to the pattern.
  For instance: the set of points {(0,0), (2,0), (2,1)} is similar to the set {(6,1), (6,5), (4,5)}, it is however not similar to the set {(4,0),(6,0), (5,-1)}.

输入:

  In the first line there is an integer T (1<=T<=15) – the number of test cases.  
  For each test case, it begin with a line including a single integer k (1 <= k <= 25000) – the number of points the pattern consists of. In the following k lines there are pairs of integers, separated by single spaces. The i+1st line contains the coordinates of ith point belonging to the pattern: x_i i y_i (-20000 <= x_i, y_i <= 20000). The points forming the pattern are pairwise different. In the next line there is the number of sets to be investigated: n (1 <= n <= 20). Next, there are n descriptions of these sets. The description of each set begins with a line containing a single integer l – the number of points belonging to that particular set (1 <= l <= 25000). These points are described in the following lines, a single point per line. The description of a point consists of two integers separated by a single space – its coordinates x, y (-20000 <= x, y <= 20000). The points which belong to the same set are pairwise different.

输出:

  In the first line there is an integer T (1<=T<=15) – the number of test cases.  
  For each test case, it begin with a line including a single integer k (1 <= k <= 25000) – the number of points the pattern consists of. In the following k lines there are pairs of integers, separated by single spaces. The i+1st line contains the coordinates of ith point belonging to the pattern: x_i i y_i (-20000 <= x_i, y_i <= 20000). The points forming the pattern are pairwise different. In the next line there is the number of sets to be investigated: n (1 <= n <= 20). Next, there are n descriptions of these sets. The description of each set begins with a line containing a single integer l – the number of points belonging to that particular set (1 <= l <= 25000). These points are described in the following lines, a single point per line. The description of a point consists of two integers separated by a single space – its coordinates x, y (-20000 <= x, y <= 20000). The points which belong to the same set are pairwise different.

样例输入:

1
3
0 0
2 0
2 1
2
3
4 1
6 5
4 5
3
4 0
6 0
5 -1

样例输出:

[pre]Yes
No

[/pre]

链接:http://acm.hdu.edu.cn/showproblem.php?pid=4613

题意: 判断一个集合中的点能不能由另一个集合中的点,通过平移,旋转,放缩得到~

思路:先求出集合中的点的凸包,然后枚举每一条边作为起点 ,看原集合中的点能否与要比较的集合中的点一一对应~

 #include <iostream>
 #include <cstdio>
 #include <algorithm>
 #include <functional>
 #include <utility>
 #include <cstring>
 #include <cmath>
 #include <complex>
 using namespace std;
 const int maxn = 25010;
 typedef complex<double> point;
 #define X real()
 #define Y imag()
 point p[maxn],s[maxn], tp[maxn],ts[maxn];
 double ang;
 int cnttp,cntts;
 int n,m,M,T;
 const double eps = 1e-9;
 int sign(double x)
 {
     if(x>eps)return 1;
     if( fabs(x)>eps )return -1;
     return 0;
 }
 
 bool cmp(const point& p1,const point& p2)
 {
     if( sign(p1.X-p2.X)==0 ) return ( sign( p1.Y-p2.Y)<0 );
     return sign( p1.X-p2.X)<0;
 }
 
 double det(const point &p1,const point& p2,const point& org)
 {
     return (p1.X - org.X) * (p2.Y - org.Y) - (p1.Y - org.Y) * (p2.X - org.X);
 }
 
 void graham(int n,point *p,int& s,point *ch)
 {
     sort(p,p + n,cmp);
     int i,s2;
     ch[0] = p[0];s = 1;
     for(i = 1;i < n;i++) {
         while(s > 1 && det(p[i],ch[s - 1],ch[s - 2])<eps)s--;
         ch[s++] = p[i];
     }
     s2 = s;
     for(int i = n - 2;i>=0;i--) {
         while(s>s2 && det(p[i],ch[s - 1],ch[s - 2])<eps)s--;
         ch[s++] = p[i];
     }
     s--;
 }
 
 double getAngle(const point& p1,const point& p2)
 {
     double dot = p1.X * p2.X + p1.Y * p2.Y;
     dot /= abs(p1) * abs(p2);
     return dot;
 }
 
 bool check(const point& org,const point& trans)
 {
     for(int i = 0;i<m;i++) {
         if(!binary_search(p,p + n,(s[i] - org) * trans + tp[0],cmp))return false;
     }
     return true;
 }
 
 void gao()
 {
     scanf("%d",&m);
     for(int i = 0 ;i<m;i++) {
         scanf("%lf%lf",&s[i].X,&s[i].Y);
     }
     if(n!=m) {puts("No");return;}
     if(n<=2){puts("Yes");return;}
     graham(m,s,cntts,ts);
     double sang;
     point org,trans;
     point A,B,C;
     for(int k=1; k<=2; ++ k){
         for(int i = 0;i<m;i++)
             s[i].X = -s[i].X;
         for(int i = 0;i<cntts;i++)
             ts[i].X = -ts[i].X;
         for(int i = 0;i<cntts;i++) {
             B = ts[i];
             A = ts[(cntts + i - 1) % cntts];
             C = ts[(i + 1) % cntts];
             sang = getAngle(A - B,C - B);
             if(fabs(sang - ang)<eps) {
                 org = B;
                 trans =  (tp[1] - tp[0]) / (A - B);
                 if(check(org,trans)) {
                     puts("Yes");
                     return;
                 }
                 trans = (tp[1] - tp[0]) / (C - B);
                 if(check(org,trans)) {
                     puts("Yes");
                     return;
                 }
             }
         }
     }
     puts("No");
     return;
 }
 
 int main()
 {
     scanf("%d",&T);
     while(T--) {
         scanf("%d",&n);
         for(int i =0;i<n;i++) {
             scanf("%lf%lf", &p[i].X, &p[i].Y);
         }
         if(n>2) {
             graham(n,p,cnttp,tp);
             ang = getAngle(tp[1] - tp[0],tp[cnttp - 1] - tp[0]);
         }
         scanf("%d",&M);
         for(int i =0 ;i<M;i++)
             gao();
         puts("");
     }
     return 0;
 }

 

参考:http://www.cnblogs.com/jian1573/archive/2013/07/29/3222602.html