POJ 1328

来源:互联网 发布:反智主义 知乎 编辑:程序博客网 时间:2024/06/05 10:31

挺恶心的一个问题,一开始思路是那种常见的选圆(先按x坐标排好),然后用最右可行坐标,然后往右判断是否能包含下面的几个点,然后循环。。。然后产生一个问题:如果当前有两个点,(0,1),(-0.0003,2)。。那么按照这种做法要两个圆。。。。然后经暗示,想到可以转化为区间问题,将每个island的可行X范围算出来,然后下面的问题就是统计有多少公共区间,,,思路就是先按起点(也可以按终点)排序,然后根据当前点,往后找,不停更新最右范围,,直到后面点的起点超出这个最右范围,此时加一个雷达(其实就是判断多少个section能在一个区间里,然后公用一个雷达)。。。。


Code:


#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#define MIS 1e-9using namespace std;int n,d;struct point{int x;int y;}pts[1005];struct interval{double s;double e;}itv[1005];bool cmp(const interval & a,const interval & b){ return a.s<b.s;}int main(){freopen("in.txt","r",stdin);int ks;while(cin >> n >> d){bool flag=true;if(n==0&& d==0) break;for(int i=0;i<n;i++) cin >> pts[i].x >> pts[i].y;for(int i=0;i<n;i++){if(pts[i].y>d) {flag=false;break;}double tx=sqrt(pow(d,2)-pow(pts[i].y,2));itv[i].s=pts[i].x-tx;itv[i].e=pts[i].x+tx;}if(!flag){printf("Case %d: -1\n",++ks); continue;}sort(itv,itv+n,cmp);int idx=0;double right;int cnt=0;while(idx<n){right=itv[idx].e;for(idx+=1;idx<n&&itv[idx].s<right+MIS;idx++){right=min(itv[idx].e,right);}cnt++;}printf("Case %d: %d\n",++ks,cnt);}return 0;}


0 0
原创粉丝点击