http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=360 //2010-07-17 12:12:55 //Accepted 1360 C++ 0 204 xiaxia //贪心算法 #include <iostream> #include <algorithm> #include <math.h> using namespace std; struct node { double lx,rx; }s[1005];//结构体 int n,r;//n:点数,r:圆半径 bool fg;//总标记 void init() { int i,x,y; for(i=0;i<n;i++) { scanf("%d%d",&x,&y); if(y>r) fg=false; if(fg)//如果出现y>r的情况就没必要再做下去了 { double t=sqrt(double((r*r)-(y*y)));//x=x1(+/-)sqrt(r*r-y*y) s[i].lx=x-t;//区间左点 s[i].rx=x+t;//区间右点 } } return; } int cmp( const void *a, const void *b ) { node *c = (node *)a; node *d = (node *)b; if( c->rx>d->rx )//根据区间右点升序排序,其实这里按左点排序也是对的 return 1; return -1; } int run() { int i,tmin,high; tmin=1; high=s[0].rx;//假设最右边区间的对应的取来是最优解 for(i=1;i<n;i++) { if( s[i].lx>high)//该点的区间的左点大于前一点的区间的右点,即不可能在同一圆上 { tmin++;//圆数+1 high = s[i].rx;//更新最右点 } else//该点区间与上点区间有交集 high = s[i].rx<high? s[i].rx:high; //更新最右点,即更新圆的位置 } return tmin;//返回最小圆数 } int main() { int min,no=0; while(1) { no++;//case no scanf("%d%d",&n,&r); if(n==0 && r==0) break; fg=true;//标记 init(); if(fg==false) { printf("Case %d: -1/n",no);//不可能的情况,即y超过了半径r continue; } qsort(s,n,sizeof(s[0]),cmp);//用快速排序,区间从小到大排序 min=run();//贪心 printf("Case %d: %d/n",no,min); } return 0; }