poj2932

来源:互联网 发布:一个程序员的自我修养 编辑:程序博客网 时间:2024/05/01 05:07
//平面上N个两两没有公共点的圆,i号圆的圆心在(xi,yi)半径ri,求所有最外层,不包含在其他圆内部的圆//如果用圆心检测的话复杂度为O(N*N)//平面扫描技术可以降低算法的复杂度,就是查看当前扫面线经过的圆左侧的时候,Y坐标上相邻最近的两个圆#include <iostream>#include <algorithm>#include <vector>#include <set>#include <utility>using namespace std;#define  MAX_N 40006static int N;static double x[MAX_N],y[MAX_N],r[MAX_N];//判断圆i是否在圆j的内部static bool inside(int i,int j){double dx =x[i] - x[j],dy = y[i] - y[j];return dx*dx + dy*dy <=r[j]*r[j];}//枚举关键点static void solve(){vector<pair<double,int> >events;//圆的左右两端的x坐标for (int i=0;i<N;++i){events.push_back(make_pair(x[i]-r[i],i));events.push_back(make_pair(x[i]+r[i],i+N));}sort(events.begin(),events.end());//平面扫描set<pair<double,int> >outers;//与扫描线相交的最外层圆的集合vector<int>res;//最外层的圆列表for (int i=0;i<events.size();++i){int id = events[i].second%N;if (events[i].second<N)//扫描的左端{set<pair<double,int> >::iterator it  = outers.lower_bound(make_pair(y[id],id));if (it!=outers.end()&&inside(id,it->second)) continue;if (it!=outers.begin()&&inside(id,(--it)->second)) continue;res.push_back(id);outers.insert(make_pair(y[id],id));}elseouters.erase(make_pair(y[id],id));}sort(res.begin(),res.end());printf("%d\n",res.size());for (int i=0;i<res.size();++i){printf("%d%c",res[i]+1,i+1==res.size()?'\n':' ');}}int main(){scanf("%d",&N);for (int i=0;i<N;++i){scanf("%lf %lf %lf",&r[i],&x[i],&y[i]);}solve();return 0;}

0 0
原创粉丝点击