HDU4116 Fruit Ninja (2011 Asia ChengDu Regional Contest)

被这道题玩死了要。。。

对每个圆枚举得到和其他圆切线斜率,两个切线之间的斜率范围是可以经过的。得到的许多斜率范围可以转化为区间覆盖,nlogn排序得解,总复杂度O(n^2logn)。

要特别处理圆相交、包含的情况。

切线的斜率范围,是按 -pi~pi 算的,算晕了很久。。

然后就是恐怖的TLE,最后发现交C++TLE,交G++就过了,额滴个神,累死了,调一晚上。。

还有,这题用sort比用qsort快了5s。。。

  1 #include<stdio.h>

  2 #include<string.h>

  3 #include<stdlib.h>

  4 #include<math.h>

  5 #include<algorithm>

  6 #include<iostream>

  7 using namespace std;

  8 const int maxn = 1 << 10 | 1;

  9 const double pi = acos(-1.0);

 10 const double eps = 1e-6;

 11 typedef struct

 12 {

 13     double x, y, r;

 14 } Cir;

 15 typedef struct

 16 {

 17     double site;

 18     bool se;

 19 } Seg;

 20 Cir ra[maxn];

 21 Seg s[maxn << 3];

 22 int n, stp, ans;

 23 inline double max(double a, double b)

 24 {

 25     return a > b ? a : b;

 26 }

 27 inline double min(double a, double b)

 28 {

 29     return a < b ? a : b;

 30 }

 31 inline double CalDis(double a, double b)

 32 {

 33     return sqrt(a * a + b * b);

 34 }

 35 inline bool IinJ(int i, int j, double ijdis)

 36 {

 37     return ra[i].r + ijdis <= ra[j].r;

 38 }

 39 inline bool IcutJ(int i, int j, double ijdis)

 40 {

 41     return ijdis <= ra[i].r + ra[j].r;

 42 }

 43 void AddSeg(double start, double end)

 44 {

 45     if(start + pi < -eps) start += 2 * pi;

 46     if(start - pi > -eps) start -= 2 * pi;

 47     if(end + pi < -eps) end += 2 * pi;

 48     if(end - pi > -eps) end -= 2 * pi;

 49     if(start - end > eps) AddSeg(start, pi - eps * 2), AddSeg(-pi, end);

 50     else

 51     {

 52         s[stp].site = start, s[stp].se = 1;

 53         ++ stp;

 54         s[stp].site = end, s[stp].se = 0;

 55         ++ stp;

 56     }

 57 }

 58 int comp(const void *a, const void *b)

 59 {

 60     if(fabs((*(Seg *)a).site - (*(Seg *)b).site) < eps)

 61         return -((*(Seg *)a).se && !(*(Seg *)b).se);

 62     return (*(Seg *)a).site > (*(Seg *)b).site ? 1 : -1;

 63 }

 64 /*

 65 //sort

 66 bool comp(const Seg &a, const Seg &b)

 67 {

 68       if(fabs(a.site - b.site) < eps)

 69             return a.se && !b.se;

 70       return a.site < b.site;

 71 }

 72 */

 73 void Cal(int i)

 74 {

 75     int sum, j;

 76     for(j = sum = stp = 0; j < n; ++ j)

 77     {

 78         if(i != j)

 79         {

 80             double ijdis = CalDis(ra[i].x - ra[j].x, ra[i].y - ra[j].y);

 81             double xlij = atan2(ra[i].y - ra[j].y, ra[i].x - ra[j].x);

 82             double xlji = atan2(ra[j].y - ra[i].y, ra[j].x - ra[i].x);

 83             double asipj = asin((ra[i].r + ra[j].r) / ijdis);

 84             double asimj = asin((ra[i].r - ra[j].r) / ijdis);

 85             if(IinJ(i, j, ijdis)) ++ sum;

 86             else if(IinJ(j, i, ijdis));

 87             else if(IcutJ(i, j, ijdis)) AddSeg(xlij + asimj, xlji - asimj);

 88             else

 89             {

 90                 AddSeg(xlji - asipj, xlji - asimj);

 91                 AddSeg(xlij + asimj, xlij + asipj);

 92             }

 93         }

 94     }

 95     qsort(s, stp, sizeof(Seg), comp);

 96     //  sort(s, s + stp, comp);

 97     for(i = 0; i < stp; ++ i)

 98     {

 99         if(s[i].se) ++ sum;

100         else -- sum;

101         if(sum > ans) ans = sum;

102     }

103     if(sum > ans) ans = sum;

104 }

105 int main()

106 {

107     int t, ca, i;

108     for(scanf("%d", &t), ca = 1; ca <= t; ++ ca)

109     {

110         scanf("%d", &n);

111         for(i = 0; i < n; ++ i)

112             scanf("%lf%lf%lf", &ra[i].x, &ra[i].y, &ra[i].r);

113         for(i = ans = 0; i < n; ++ i) Cal(i);

114         printf("Case #%d: %d\n", ca, ans + 1);

115     }

116     return 0;

117 }

 

 

 

你可能感兴趣的:(test)