hdu3511-Prison Break

纪念一下人生中第一道扫描线算法的题。。。。。其实不是严格上的第一道。。。第一次遇到的那个至今没过。。。。。

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=3511

这题应该算是扫描线的基础题。

对于每个圆,进入和出去的时候分别做扫描线,分别是x = c[i].x - c[i].r, x' = c[i].x + c[i].r;

这样对于每条扫描线,对于x',我们在集合中删去这个圆,这很好理解。

对于x,我们将这个圆加入集合,这样我们只要找向上第一个交的点和向下第一个交的点即可。

不过问题来了,这个交点坐标随着扫描线的移动是在变化的,但我们注意到,这些点的相对位置并不变(即上面的还在上面,下面的还在下面)

这样我们可以拉个set来维护扫描线上交点纵坐标,这个没必要存这个纵坐标的具体值,因为相对位置不变,树的结构也不变。

只需要重载一下小于号在insert时候使用即可。

如果扫描线向上或向下没有点,那么这个圆的depth = 1;

如果上下两个点属于同一个圆id,那么这个圆的depth = depth[id]+1;

如果上下两个圆属于不同的圆id1,id2,那么这个圆的depth = max(depth[id1], depth[id2]);

AC代码:

  1 #include <bits/stdc++.h>
  2 
  3 using namespace std;
  4 const int maxn = 50000 + 10;
  5 
  6 typedef struct Circle{
  7   int id, x, y, r;
  8 
  9   Circle( int id = 0, int x = 0, int y = 0, int r = 0 ){
 10     this->id = id;
 11     this->x = x;
 12     this->y = y;
 13     this->r = r;
 14   }
 15 }Circle;
 16 
 17 Circle c[maxn];
 18 
 19 typedef struct Point{
 20   int id, ty;
 21 
 22   Point( int id = 0, int ty = 0 ){
 23     this->id = id;
 24     this->ty = ty;
 25   }
 26 }Point;
 27 
 28 set<Point> s;
 29 
 30 typedef struct Line{
 31   int id, x, ty;
 32 
 33   Line( int id = 0, int x = 0, int ty = 0 ){
 34     this->id = id;
 35     this->x = x;
 36     this->ty = ty;
 37   }
 38 
 39   bool operator < ( const Line& l )const{
 40     if( x == l.x )
 41       return id < l.id;
 42     return x < l.x;
 43   }
 44 }Line;
 45 
 46 Line l[maxn<<1];
 47 
 48 int depth[maxn];
 49 
 50 int n, ans, xlog;
 51 
 52 double intersector( const Point& p ){
 53   int id = p.id;
 54   double r = 1.0*c[id].r;
 55 
 56   double x = 1.0*(xlog - c[id].x);
 57   double y = sqrt((r*r - x*x));
 58 
 59   if(p.ty == 1)
 60     return 1.0*c[id].y + y;
 61   else
 62     return 1.0*c[id].y - y;
 63 }
 64 
 65 bool operator < ( const Point& p1, const Point& p2 ){
 66   if(p1.id == p2.id)
 67     return p1.ty < p2.ty;
 68   return intersector(p1) < intersector(p2);
 69 }
 70 
 71 void solve( int nn ){
 72   memset(depth, 0, sizeof(depth));
 73   s.clear();
 74   ans = 0;
 75 
 76   for( int i = 0; i < nn; ++i ){
 77     int id = l[i].id, ty = l[i].ty;
 78     xlog = l[i].x;
 79     //cout << "id: " << id << "   ty: " << ty << endl;
 80 
 81     if( ty == 1 ){
 82       s.erase(Point(id, 0));
 83       s.erase(Point(id, 1));
 84     }else{
 85       s.insert(Point(id, 0));
 86       set<Point>::iterator it1 = s.find(Point(id, 0)), it2;
 87       it2 = it1;
 88       it2++;
 89 
 90       if( it1 == s.begin() || it2 == s.end() ){
 91         depth[id] = 1;
 92         //cout << "id: " << id << "    depth[id]: " << depth[id] << endl;
 93       }else{
 94         it1--;
 95         if( it1->id == it2->id ){
 96           depth[id] = depth[it1->id]+1;
 97         }else{
 98           depth[id] = max( depth[it1->id], depth[it2->id] );
 99         }
100         //cout << "id: " << id << "    depth[id]: " << depth[id] << endl;
101       }
102       s.insert(Point(id, 1));
103     }
104     ans = max( ans, depth[id]);
105   }
106 
107   printf("%d
", ans);
108 }
109 
110 int main(void){
111   while(scanf("%d", &n) != EOF){
112     memset( c, 0, sizeof(c) );
113     memset( l, 0, sizeof(l) );
114 
115     for( int i = 0; i < n; ++i ){
116       c[i].id = i;
117       scanf("%d%d%d", &c[i].x, &c[i].y, &c[i].r);
118       l[i*2] = Line(i, c[i].x-c[i].r, 0);
119       l[i*2+1] = Line(i, c[i].x+c[i].r, 1);
120     }
121     int nn = n * 2;
122     sort( l, l + nn );
123 
124     solve(nn);
125   }
126 
127   return 0;
128 }
129 
130 /*
131 5
132 0 0 100
133 0 0 1
134 0 5 3
135 3 0 2
136 0 0 200
137 6
138 0 0 100
139 0 0 1
140 0 5 3
141 0 5 2
142 3 0 2
143 0 0 200
144 */
View Code
原文地址:https://www.cnblogs.com/zhazhalovecoding/p/5403894.html