hdu 4613 Points<计算几何>

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

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

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

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <algorithm>
  4 #include <functional>
  5 #include <utility>
  6 #include <cstring>
  7 #include <cmath>
  8 #include <complex>
  9 using namespace std;
 10 const int maxn = 25010;
 11 typedef complex<double> point;
 12 #define X real()
 13 #define Y imag()
 14 point p[maxn],s[maxn], tp[maxn],ts[maxn];
 15 double ang;
 16 int cnttp,cntts;
 17 int n,m,M,T;
 18 const double eps = 1e-9;
 19 int sign(double x)
 20 {
 21     if(x>eps)return 1;
 22     if( fabs(x)>eps )return -1;
 23     return 0;
 24 }
 25 
 26 bool cmp(const point& p1,const point& p2)
 27 {
 28     if( sign(p1.X-p2.X)==0 ) return ( sign( p1.Y-p2.Y)<0 );
 29     return sign( p1.X-p2.X)<0;
 30 }
 31 
 32 double det(const point &p1,const point& p2,const point& org)
 33 {
 34     return (p1.X - org.X) * (p2.Y - org.Y) - (p1.Y - org.Y) * (p2.X - org.X);
 35 }
 36 
 37 void graham(int n,point *p,int& s,point *ch)
 38 {
 39     sort(p,p + n,cmp);
 40     int i,s2;
 41     ch[0] = p[0];s = 1;
 42     for(i = 1;i < n;i++) {
 43         while(s > 1 && det(p[i],ch[s - 1],ch[s - 2])<eps)s--;
 44         ch[s++] = p[i];
 45     }
 46     s2 = s;
 47     for(int i = n - 2;i>=0;i--) {
 48         while(s>s2 && det(p[i],ch[s - 1],ch[s - 2])<eps)s--;
 49         ch[s++] = p[i];
 50     }
 51     s--;
 52 }
 53 
 54 double getAngle(const point& p1,const point& p2)
 55 {
 56     double dot = p1.X * p2.X + p1.Y * p2.Y;
 57     dot /= abs(p1) * abs(p2);
 58     return dot;
 59 }
 60 
 61 bool check(const point& org,const point& trans)
 62 {
 63     for(int i = 0;i<m;i++) {
 64         if(!binary_search(p,p + n,(s[i] - org) * trans + tp[0],cmp))return false;
 65     }
 66     return true;
 67 }
 68 
 69 void gao()
 70 {
 71     scanf("%d",&m);
 72     for(int i = 0 ;i<m;i++) {
 73         scanf("%lf%lf",&s[i].X,&s[i].Y);
 74     }
 75     if(n!=m) {puts("No");return;}
 76     if(n<=2){puts("Yes");return;}
 77     graham(m,s,cntts,ts);
 78     double sang;
 79     point org,trans;
 80     point A,B,C;
 81     for(int k=1; k<=2; ++ k){
 82         for(int i = 0;i<m;i++)
 83             s[i].X = -s[i].X;
 84         for(int i = 0;i<cntts;i++)
 85             ts[i].X = -ts[i].X;
 86         for(int i = 0;i<cntts;i++) {
 87             B = ts[i];
 88             A = ts[(cntts + i - 1) % cntts];
 89             C = ts[(i + 1) % cntts];
 90             sang = getAngle(A - B,C - B);
 91             if(fabs(sang - ang)<eps) {
 92                 org = B;
 93                 trans =  (tp[1] - tp[0]) / (A - B);
 94                 if(check(org,trans)) {
 95                     puts("Yes");
 96                     return;
 97                 }
 98                 trans = (tp[1] - tp[0]) / (C - B);
 99                 if(check(org,trans)) {
100                     puts("Yes");
101                     return;
102                 }
103             }
104         }
105     }
106     puts("No");
107     return;
108 }
109 
110 int main()
111 {
112     scanf("%d",&T);
113     while(T--) {
114         scanf("%d",&n);
115         for(int i =0;i<n;i++) {
116             scanf("%lf%lf", &p[i].X, &p[i].Y);
117         }
118         if(n>2) {
119             graham(n,p,cnttp,tp);
120             ang = getAngle(tp[1] - tp[0],tp[cnttp - 1] - tp[0]);
121         }
122         scanf("%d",&M);
123         for(int i =0 ;i<M;i++)
124             gao();
125         puts("");
126     }
127     return 0;
128 }
View Code
原文地址:https://www.cnblogs.com/jian1573/p/3222602.html