这是一道喜闻乐见 的贪心题
感觉这题最大的坑点在 格 式 \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;
}
最后注意输出格式!