简介:
用最少圆覆盖矩形
分析:
我们通过分析可以发现
半径小于等于r的圆是完全没有用的
而每个圆能够有效覆盖的面积只有:
因此我们在输入的时候,预处理一下每个圆可以覆盖的矩形的左端点和右端点
这样我们就把问题转化成了贪心的经典问题:
区间覆盖
我们把所有的区间按照端点排序,
- 注意,如果某一区间边界大于s,t的边界,应把它们变成s或t
因为超出的部分毫无意义,同时还会影响对数据的分析
设当前覆盖完的区间为w
每次选择左端点小于等于w,右端点尽量大的区间x作为下一个选中区间
同时把w修改为right[x]
int ans=0;
double left=0,right=0;
bool ff=0;
int i=1;
if (dcmp(po[1].x)<=0)
while (i<=cnt)
{
int j=i;
while (j<=cnt && dcmp(left-po[j].x)>=0)
{
if (dcmp(po[j].y-right)>0)
right=po[j].y;
j++;
}
if (i==j) break; //如果上面的循环没有执行,说明没有满足的了
++ans;
left=right;
i=j;
if (dcmp(left-l)==0)
{
ff=1;
break;
}
}
if (ff) printf("%d\n",ans);
else printf("-1\n");
tip
注意无解的输出
//这里写代码片
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
const double eps=1e-8;
const int N=10010;
double l,w;
int n;
struct node{
double x,y;
};
node po[N];
int dcmp(double x)
{
if (fabs(x)<eps) return 0;
else if (x>0) return 1;
else return -1;
}
bool operator < (const node &a,const node &b)
{
return a.x<b.x;
}
double Len(double x,double y)
{
return sqrt(x*x-y*y);
}
int main()
{
while (scanf("%d%lf%lf",&n,&l,&w)!=EOF&&n)
{
double p,r;
int cnt=0;
for (int i=1;i<=n;i++)
{
scanf("%lf%lf",&p,&r);
if (r<=w/2) continue; //半径过小的没用
double ll=Len(r,w/2);
po[++cnt].x=p-ll;
po[cnt].y=p+ll;
if (dcmp(po[cnt].x)<0) po[cnt].x=0;
if (dcmp(po[cnt].y-l)>0) po[cnt].y=l;
}
sort(po+1,po+1+cnt);
int ans=0;
double left=0,right=0;
bool ff=0;
int i=1;
if (dcmp(po[1].x)<=0)
while (i<=cnt)
{
int j=i;
while (j<=cnt && dcmp(left-po[j].x)>=0)
{
if (dcmp(po[j].y-right)>0)
right=po[j].y;
j++;
}
if (i==j) break; //如果上面的循环没有执行,说明没有满足的了
++ans;
left=right;
i=j;
if (dcmp(left-l)==0)
{
ff=1;
break;
}
}
if (ff) printf("%d\n",ans);
else printf("-1\n");
}
return 0;
}