[扫描线]POJ2932 Coneology
题意:有n个圆 依次给了半径和圆心坐标 保证输入的圆不相交(只有 相离 和 内含/外含 的情况)
问 有几个圆 不内含在其他圆中,并分别列出这几个圆的编号(1~n)
(n的范围是[1, 40000])
案例画出来大概是这样的
(那个原点为(50,50)的太远了,就意思一下)
所以答案是3号圆和5号圆 不被包含
好了,若这道题n只有1000,那么只要for两层,每个圆与另外的圆比较, 判断圆心是否在其他圆内即可判断是否包含
这样的复杂度是O($n^2$)
可是现在n有40000,显然不能用O($n^2$)来解决
由这道题,简单粗暴的学习了一下扫描线, 复杂度为O(nlogn)
什么是扫描线呢?
顾名思义,就是一根线,扫描过去。
怎样的一根线,怎么扫过去呢?
①平行于x轴,自上而下/自下而上 扫描
②平行于y轴,自左而右/自右而左 扫描
③绕圆心 逆时针/顺时针 扫描
扫描线要干什么呢?
“扫描线在平面上按给定轨迹移动的同时,不断根据扫描线扫过部分更新信息,从而得到整体所要求的结果”
这道题,可以用上述的①/②
自左而右扫描时,只有当扫描线移动到圆的左右两端时,线与圆的关系才会发生改变,因此先把圆的左右端点取出来排个序
每当遇到某圆的左端点,判断该圆是否包含在其他圆内
因为所有的圆都不相交,因此,每个圆都只可能包含在上下两个与它最相近的圆中
(此处“上下两个”是通过比较 圆心的纵坐标 来确定的)
也就是 每当我们得到一个不包含在其他圆中的圆,我们需要将它存起来,并将这些圆按圆心的纵坐标排序 以便与下一个扫到的圆进行比较
我们可以用set<pair<double, int> >来存 (pair.first是圆心的纵坐标,pair.second是圆的编号) set会自动按pair.first排序
当我们扫到某圆的右端点时,表示该圆的影响范围已经扫完了,后面扫到的圆不可能包含在该圆中,因此可以把该圆从set中去掉
查找“上下两个与它最近的圆”的复杂度为O(logn)
因此遍历n个圆的复杂度为O(nlogn)
const int N=; double x[N], y[N] ,r[N]; bool inside(int i, int j) // i是否在j内
{
double dx=x[i]-x[j], dy=y[i]-y[j];
return dx*dx+dy*dy<=r[j]*r[j];
} int main()
{
int n;
while(~scanf("%d", &n))
{
for(int i=;i<n;i++)
scanf("%lf%lf%lf", &r[i], &x[i], &y[i]);
vector<pair<double, int> > X;
for(int i=;i<n;i++)
{
X.push_back(make_pair(x[i]-r[i], i)); // 左
X.push_back(make_pair(x[i]+r[i], i+n));// 右
}
sort(X.begin(), X.end());
set<pair<double, int> > out;
vector<int> ans;
for(int i=;i<X.size();i++) // 从左到右扫描
{
int id=X[i].second%n;
if(X[i].second<n) // 左
{
set<pair<double, int> >::iterator it=out.lower_bound(make_pair(y[id], id));
if(it!=out.end() && inside(id, it->second)) // id 在 前一个圆内 不加入
continue;
if(it!=out.begin() && inside(id, (--it)->second)) // id 在 后一个圆内 不加入
continue;
ans.push_back(id);
out.insert(make_pair(y[id], id));
}
else // 右
out.erase(make_pair(y[id], id));
}
sort(ans.begin(), ans.end());
printf("%d\n", ans.size());
for(int i=;i<ans.size();i++)
printf("%d%c", ans[i]+, i+==ans.size()? '\n':' ');
}
return ;
}
POJ 2932
[扫描线]POJ2932 Coneology的更多相关文章
- POJ2932 Coneology【圆扫描线】
POJ2932 Coneology 题意: 给出一些不相交的圆,问有多少个圆不被其他圆包围 题解: 扫描线,把所有圆的左边界和右边界放到\(vector\)里排序,遍历到圆左边界的时候判断是否满足条件 ...
- poj2932 Coneology (扫描线)
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud Coneology Time Limit: 5000MS Memory Lim ...
- 计算几何值平面扫面poj2932 Coneology
Coneology Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 4097 Accepted: 859 Descript ...
- poj2932 Coneology
地址:http://poj.org/problem?id=2932 题目: Coneology Time Limit: 5000MS Memory Limit: 65536K Total Subm ...
- 刷题总结——coneology(poj2932 扫描线)
题目: Description A student named Round Square loved to play with cones. He would arrange cones with d ...
- poj 2932 Coneology(扫描线+set)
Coneology Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 3574 Accepted: 680 Descript ...
- poj 2932 Coneology (扫描线)
题意 平面上有N个两两不相交的圆,求全部最外层的,即不被其它圆包括的圆的个数并输出 思路 挑战程序竞赛P259页 代码 /* ************************************* ...
- POJ 2932 Coneology(扫描线)
[题目链接] http://poj.org/problem?id=2932 [题目大意] 给出N个两两没有公共点的圆,求所有不包含于其它圆内部的圆 [题解] 我们计算出所有点在圆心所有y位置的x值, ...
- Coneology(POJ 2932)
原题如下: Coneology Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 4937 Accepted: 1086 D ...
随机推荐
- gdb/valgrind/coredump to debug c/cpp program
gdb/valgrind/coredump 调试 1.gdb 调试 while/for 循环 ①如果在调试 while/for的时候,可以用until xxx(其中,xxx代表 行号)直接跳转到循环后 ...
- CAF(C++ actor framework)使用随笔(使用类去构建actor和使用的一些思路)
Class-based actorsA class-based actor is a subtype of event_based_actor and must implement the pure ...
- [java学习笔记]java语言基础概述之运算符&程序流程控制&for循环嵌套
一.运算符 算数运算符 +,-,*,/,%,++,-- 1.+,-,*,/ 整数除以整数的结果为舍弃了小数部分的整数. 2.%:取余 %左右都为正数,左边小于右边结果为左边值,如,4%5=4 %左边大 ...
- WMB代理无法正常启动时的解决方案。
情况:执行了启动命令,查看状态的时候 还是停止..再启动,又说已经启动了.. 解决方案:正常情况在hosts文件加一条记录:主机IP和hostname的映射关系就好了
- JPA && Spring Data && Spring Data JPA
1.JPA Java Persistence API,用于对象持久化的一组API,JPA本身是一组规范,让开发者用同一种方式访问不同的ORM框架.其实也就是java实体对象和关系型数据库建立起映射关 ...
- Nhibernate的log4net和系统的log4net使用技巧
NHibernate定义了两个logger:NHibernate和NHibernate.SQL.我们可以分别配置这两个logger.在App.config文件中<root>标签前边添加如下 ...
- android 获取手机号
android 获取手机号码,由于运营商的管理方式的不同,所以获取手机号码的方式也可能完全相同.现在很多运营商并不会把手机号码存入sim卡中. 最简单的,比如说中国移动并不将手机号保存在sim卡中,只 ...
- 定时备份服务器数据库(借助windows任务计划以及mysqldump)
最近社区多了,考虑到数据的安全性,要每天备份一次数据库,以防万一: linux目前还不是很了解,先用windows的计划任务吧: 大体思路就是 借用windows的计划任务来执行备份远程数据库到本地: ...
- 购买 CDRTools 2 正式版
联系方式: Email:396390927@qq.com QQ: 396390927 QQ群: 26326434 组件价格: ¥50元/用户,免费更新: 此物为数字商品,并经过测试完全可用,谢 ...
- 【原创】一起学C++ 之指针的--/++ ---------C++ primer plus(第6版)
讲*和++同时用于指针时提出了这样的问题:将什么解除引用,将什么递增. ]={21.1, 32.8, 23.4, 45.2, 37.4 }; double *pt=arr; //pt指针指向arr[0 ...