大意是x轴上方有n个目标点,坐标全为整数,为了扫描到他们,在x轴上安放雷达,每一个雷达扫描半径为d,问至少安放多少雷达。
首先想到的是化归。找出每一点在x轴上的扫描边界,即在这个范围内必须有雷达才能扫描到。这样便将问题化归为:给n个闭区间,找出最少的点,保证每个区间至少有一个点。
贪心算法:我们先将问题的区间集合按右端点排序,从最左边的区间开始,如果该区间内雷达为空为空,则选区间最右边的端点放雷达,并删掉左端点在雷达前的区间,进入子问题。
// // main.cpp // poj1328 // // Created by Fangpin on 15/5/21. // Copyright (c) 2015年 FangPin. All rights reserved. // #include <iostream> #include <vector> #include <cstdio> #include <cmath> #include <algorithm> using namespace std; struct Node{ double l,r; }; bool cmp(const Node& x,const Node& y){ return x.r<y.r; } int main(int argc, const char * argv[]) { // insert code here... // std::cout << "Hello, World!\n"; int n,d,ca=1; while(scanf("%d%d",&n,&d),n+d){ vector<Node> vec; vec.clear(); bool flag=true; for(int i=0;i<n;++i){ int x,y; scanf("%d%d",&x,&y); if(y>d) flag=false; vec.push_back(Node{x-sqrt(d*d-y*y),x+sqrt(d*d-y*y)}); } if(!flag){ printf("Case %d: -1\n",ca++); continue; } sort(vec.begin(),vec.end(),cmp); int cnt=0; double pre=-1e10; for(int i=0;i<n;++i){ if(vec[i].l>pre){ pre=vec[i].r; ++cnt; } } printf("Case %d: %d\n",ca++,cnt); } return 0; }
原文:http://blog.csdn.net/fangpinlei/article/details/45896573