您的位置:首页 > 其它

hdu3511-Prison Break

2016-04-18 11:55 323 查看
纪念一下人生中第一道扫描线算法的题。。。。。其实不是严格上的第一道。。。第一次遇到的那个至今没过。。。。。

题目链接:
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代码:

#include <bits/stdc++.h>

using namespace std;
const int maxn = 50000 + 10;

typedef struct Circle{
int id, x, y, r;

Circle( int id = 0, int x = 0, int y = 0, int r = 0 ){
this->id = id;
this->x = x;
this->y = y;
this->r = r;
}
}Circle;

Circle c[maxn];

typedef struct Point{
int id, ty;

Point( int id = 0, int ty = 0 ){
this->id = id;
this->ty = ty;
}
}Point;

set<Point> s;

typedef struct Line{
int id, x, ty;

Line( int id = 0, int x = 0, int ty = 0 ){
this->id = id;
this->x = x;
this->ty = ty;
}

bool operator < ( const Line& l )const{
if( x == l.x )
return id < l.id;
return x < l.x;
}
}Line;

Line l[maxn<<1];

int depth[maxn];

int n, ans, xlog;

double intersector( const Point& p ){
int id = p.id;
double r = 1.0*c[id].r;

double x = 1.0*(xlog - c[id].x);
double y = sqrt((r*r - x*x));

if(p.ty == 1)
return 1.0*c[id].y + y;
else
return 1.0*c[id].y - y;
}

bool operator < ( const Point& p1, const Point& p2 ){
if(p1.id == p2.id)
return p1.ty < p2.ty;
return intersector(p1) < intersector(p2);
}

void solve( int nn ){
memset(depth, 0, sizeof(depth));
s.clear();
ans = 0;

for( int i = 0; i < nn; ++i ){
int id = l[i].id, ty = l[i].ty;
xlog = l[i].x;
//cout << "id: " << id << "   ty: " << ty << endl;

if( ty == 1 ){
s.erase(Point(id, 0));
s.erase(Point(id, 1));
}else{
s.insert(Point(id, 0));
set<Point>::iterator it1 = s.find(Point(id, 0)), it2;
it2 = it1;
it2++;

if( it1 == s.begin() || it2 == s.end() ){
depth[id] = 1;
//cout << "id: " << id << "    depth[id]: " << depth[id] << endl;
}else{
it1--;
if( it1->id == it2->id ){
depth[id] = depth[it1->id]+1;
}else{
depth[id] = max( depth[it1->id], depth[it2->id] );
}
//cout << "id: " << id << "    depth[id]: " << depth[id] << endl;
}
s.insert(Point(id, 1));
}
ans = max( ans, depth[id]);
}

printf("%d\n", ans);
}

int main(void){
while(scanf("%d", &n) != EOF){
memset( c, 0, sizeof(c) );
memset( l, 0, sizeof(l) );

for( int i = 0; i < n; ++i ){
c[i].id = i;
scanf("%d%d%d", &c[i].x, &c[i].y, &c[i].r);
l[i*2] = Line(i, c[i].x-c[i].r, 0);
l[i*2+1] = Line(i, c[i].x+c[i].r, 1);
}
int nn = n * 2;
sort( l, l + nn );

solve(nn);
}

return 0;
}

/*
5
0 0 100
0 0 1
0 5 3
3 0 2
0 0 200
6
0 0 100
0 0 1
0 5 3
0 5 2
3 0 2
0 0 200
*/


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: