这是一道喜闻乐见 的贪心题
感觉这题最大的坑点在 格 式 \blue{格式} 格式,我因为格式问题 W A \red{WA} WA了至少 10 10 10次。
思路:
感觉这题比较经典,且有一点思维含量,但是考的算法并不高深。 ( 所 以 C S P 应 该 不 会 考 ? ? ) (~~所以CSP应该不会考??~~ ) ( 所以CSP应该不会考?? )题目大意为:一组圆 C i − m C_{i-m} Ci−m的纵坐标已经固定,横坐标不确定,半径为 d d d。给定一组点 P 1 − n P_{1-n} P1−n,求 m m m的最小值使得这 n n n个点均在这些圆内。
‘
至此问题已经被我们转化为了计算几何题。我们定义结构体
struct point
{
int x;int y;
double l;double r;
};point p[1005];
来储存这些点。我们不妨反过来想:既然圆的半径已经固定,那么对于一个点 P i P_i Pi,能包含其的圆 C i C_i Ci的圆心横坐标范围被唯一确定,由勾股定理可以得到:
x C ∈ [ x p − d 2 − y p 2 , x p + d 2 − p 2 ] x_C\in[x_p-\sqrt{d^2-y_p^2},x_p+\sqrt{d^2-p^2}] xC∈[xp−d2−yp2,xp+d2−p2]
将这些区间左端点做递增排序,就能类似于种树问题的贪心了。
A C c o d e : \green{AC\space code:} AC code:
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
struct point
{
int x;int y;
double l;double r;
};point p[1005];
int n,d,cnt=1;
int flag=true;
inline double cal_del(point p)
{
double delta=d*d*1.0-p.y*p.y;
return sqrt(delta);
}
inline bool cmp(point p1,point p2)
{
return p1.l<p2.l;
}
int main()
{
while(cin>>n>>d)
{
if(n==0||d==0) break;
for(int i=1;i<=n;i++)
{
int x0,y0;
cin>>x0>>y0;
if(y0>d) flag=false;
p[i].x=x0;
p[i].y=y0;
p[i].l=x0-cal_del(p[i]);
p[i].r=x0+cal_del(p[i]);
}
if(!flag)
{
cout<<"Case "<<cnt<<": "<<-1<<endl;
}
else
{
sort(p+1,p+n+1,cmp);
int tot=1;
int now=1;
for(int i=2;i<=n;i++)
{
if(p[i].l>p[now].r)
{
tot++;
now=i;
}
else if(p[i].r<p[now].r)
{
now=i;
}
}
cout<<"Case "<<cnt<<": "<<tot<<endl;
for(int i=1;i<=n;i++)
{
cout<<p[i].l<<" ";
}
}
cnt++;
}
return 0;
}
最后注意输出格式!