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\n", 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 */