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代码:
View Code
题目链接:
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
相关文章推荐
- [ASP.NET MVC] Real-time之HTML5 服务器发送事件(server-sent event)
- iOS 多语言支持
- 查看服务器上文件占用磁盘容量
- 友元类
- java.io.file 中mkdir和mkdirs的区别
- Apache新版配置虚拟主机的注意事项
- HashMap和Hashtable的区别
- json 解析 -转载
- Apache新版配置虚拟主机的注意事项
- json接口
- 线程池ThreadPoolExecutor
- About Ubuntu
- 使用EditPlus和批处理删除文本重复内容行
- 深圳市高级工商管理研究会成立大会成功召开
- 校验手机号/座机号的表单
- 为什么大公司的高管出来创业会失败?
- 每日开源新闻速递(2016/4/18):Ubuntu 16.04 支持 Docker 1.10
- ButterKnife--View注入框架
- synergy 无法连接
- iOS数据持久化之归档NSKeyedArchiver