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 }

你可能感兴趣的:(USACO)