BZOJ2592: [Usaco2012 Feb]Symmetry
特别选出其中两个点,比如p[0]和p[1],两个点要么在对称轴上,要么一个在对称轴上,要么是对称点,要么分别和其他点对称而共享一个对称轴。
这样枚举其他点和这两点构成对称轴,可以枚举出2n个对称轴,复杂度是O(n),中间判断一下是否其中一个点在对称轴上。
对于枚举得到的O(n)个对称轴,用set或hash的方法存点,就可以通过计算对称点是否存在的方法O(nlogn)或O(n)来判断是否是对称轴了。
没想到36ms,set还挺快。
1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 #include<math.h> 5 #include<algorithm> 6 #include<set> 7 using namespace std; 8 const int maxn = 1111; 9 const double eps = 1e-8; 10 const double pi = acos(-1.0); 11 int dcmp(double x) {return (x > eps) - (x < -eps);} 12 inline double Sqr(double x) {return x * x;} 13 /**************************************************/ 14 struct Point 15 { 16 double x, y; 17 Point(){x = y = 0;} 18 Point(double a, double b) 19 {x = a, y = b;} 20 inline Point operator-(const Point &b)const 21 {return Point(x - b.x, y - b.y);} 22 inline Point operator+(const Point &b)const 23 {return Point(x + b.x, y + b.y);} 24 inline Point operator*(const double &b)const 25 {return Point(x * b, y * b);} 26 inline double dot(const Point &b)const 27 {return x * b.x + y * b.y;} 28 inline double cross(const Point &b, const Point &c)const 29 {return (b.x - x) * (c.y - y) - (c.x - x) * (b.y - y);} 30 inline bool operator<(const Point &b)const 31 {return dcmp(x - b.x) ? x < b.x : y < b.y;} 32 inline bool operator==(const Point &b)const 33 {return !dcmp(x - b.x) && !dcmp(y - b.y);} 34 }; 35 int n; 36 Point p[maxn], mps, mpe; 37 set<Point> s; 38 Point LineCross(const Point &a, const Point &b, const Point &c, const Point &d) 39 { 40 double u = a.cross(b, c), v = b.cross(a, d); 41 return Point((c.x * v + d.x * u) / (u + v), (c.y * v + d.y * u) / (u + v)); 42 } 43 Point AntiPoint(const Point &p, const Point &a, const Point &b) 44 { 45 if(a == b) return Point(a.x + a.x - p.x, a.y + a.y - p.y); 46 Point tmp(p.x + a.y - b.y, p.y + b.x - a.x); 47 return LineCross(p, tmp, a, b) * 2 - p; 48 } 49 bool Judge(Point a, Point b) 50 { 51 for(int i = 0; i < n; ++ i) 52 if(!s.count(AntiPoint(p[i], a, b))) return false; 53 return true; 54 } 55 bool MakeMP(Point a, Point b, Point &c, Point &d) 56 { 57 if(a == b) return false; 58 c = (a + b) * 0.5; 59 d = Point(c.x + a.y - b.y, c.y + b.x - a.x); 60 return true; 61 } 62 63 int main() 64 { 65 int i, ans; 66 while(scanf("%d", &n) != EOF) 67 { 68 s.clear(); 69 for(i = 0; i < n; ++ i) scanf("%lf%lf", &p[i].x, &p[i].y), s.insert(p[i]); 70 ans = Judge(p[0], p[1]); 71 MakeMP(p[0], p[1], mps, mpe); 72 ans += Judge(mps, mpe); 73 for(i = 2; i < n; ++ i) 74 { 75 MakeMP(p[0], p[i], mps, mpe); 76 ans += Judge(mps, mpe); 77 MakeMP(p[1], p[i], mps, mpe); 78 ans += Judge(mps, mpe) && !dcmp(p[0].cross(mps, mpe)); 79 } 80 printf("%d\n", ans); 81 } 82 return 0; 83 }