poj1328
链接:http://poj.org/problem?id=1328
典型的贪心算法
这里是一些大牛的分析,小弟不才,借鉴用下,有些不是很理解
正确的算法是:要考虑把雷达站放到哪个位置使得包含雷达的区间最多!
写算法的时候要注意,按海岛的横坐标排序(纵坐标是跟随横坐标,但不能对排序构成任何影响)后,第一个雷达建立在区间的右端,然后依次判断每个区间的左端点,如果在最新建立的雷达右面,那么肯定需要一个雷达,而且也建在区间右端。如果左端点在雷达左面,这个时候要考虑区间的右端在雷达的左面还是右面,如果是右面,那雷达位置就不变,如果在左面,那现在的雷达是覆盖不了的,所以要把雷达放在该区间的右端点!因为这样同时不但能覆盖原来的岛,还能覆盖现在的岛
标准方法是把每个点的放置雷达的区间求出,然后按照区间排序。排好序后,从左至右看,当发现下一个区间的起始点大于前面所有区间的最小结束点的时候,答案加一。忽视前面走过的所有点后,对后面进行相同的操作(从左至右看,当发现下一个区间的起始点大于左边未被忽视的所有区间的最小结束点的时候,答案加一)。直到结束。但是这样做相对较难实现。
红色字体可谓是点睛之笔,细细体会,这正是贪心所在
#include <iostream> #include <algorithm> #include <math.h> using namespace std; struct point { double x; double y; }; struct area { double l; double r; }; point p[1005]; area a[1005]; int cmp(area a, area b) { return a.l<b.l ; } int min(int a,int b) { return a<b?a:b; } int main() { int i; int n,d; int t=0; while(true) { t++; int count =1; cin>>n>>d; if(n==0 && d==0) break; for(i=0;i<n;i++) cin>>p[i].x>>p[i].y; for(i=0;i<n;i++) { if(d>=fabs(p[i].y)) { a[i].l=p[i].x-sqrt(d*d-p[i].y*p[i].y); a[i].r=p[i].x+sqrt(d*d-p[i].y*p[i].y); } else {count=-1;break;} } if(count==-1) { cout<<"Case "<<t<<": "<<count<<endl; continue;} sort(a,a+n,cmp); double left=a[0].l; double right=a[0].r; for(i=1;i<n;i++) { if(a[i].l<=right)//////////////////////////////////////////////注意取等号也成立 { left=a[i].l; right=min(right,a[i].r); } else { count++; left=a[i].l; right=a[i].r; } } cout<<"Case "<<t<<": "<<count<<endl; } return 0; }