【贪心算法】POJ1328
题目:http://poj.org/problem?id=1328
思路
假设有n个小岛,我们按照每个小岛为圆心画一个半径为d的圆形,这个圆形会割x轴,形成一个区间,我们记它为
[
l
i
,
r
i
]
[l_i,r_i]
[li,ri],即如果雷达安装在这个区间中,这个小岛就被雷达覆盖了。
那么这么一来,我们就将原题目化简为:
假设存在n个区间: [ l i , r i ] [l_i,r_i] [li,ri],我们向区间中散"芝麻",为确保每个区间中至少存在一粒芝麻,请问最少需要多少粒芝麻?
化简以后,这是典型的贪心算法,我们不妨将n个区间,按照
l
i
l_i
li进行排序,确保
l
i
≤
l
j
(
i
<
j
)
l_i\le l_j\space (i<j)
li≤lj (i<j)。
我们假设最开始在
I
1
I_1
I1中有一粒芝麻,
I
1
=
[
l
1
,
r
1
]
I_1=[l_1,r_1]
I1=[l1,r1],
I
2
=
[
l
2
,
r
2
]
I_2=[l_2,r_2]
I2=[l2,r2],则它们两的关系只有3种
- l 2 > r 1 l_2>r_1 l2>r1,即此时两区间不相交,这时 I 1 I_1 I1是一个separate的,(因为对于 I 3 , I 4 , . . . I_3,I_4,... I3,I4,...,它们都和 I 1 I_1 I1不相交),则我们需要新增一粒芝麻放在 I 2 I_2 I2中,并且此时我们已经不关心 I 1 I_1 I1了,我们将它抛弃。
- l 2 ≤ r 1 且 r 2 ≤ r 1 l_2\le r_1 且r_2\le r_1 l2≤r1且r2≤r1,这时 I 1 I_1 I1包含 I 2 I_2 I2,这时我们不需要新增芝麻,只需将原来在 I 1 I_1 I1中的芝麻,移动到 I 2 I_2 I2中,就行了,而且此时我们也要抛弃 I 1 I_1 I1,因为芝麻只能在 I 2 I_2 I2中移动
- l 2 ≤ r 1 且 r 2 > r 1 l_2\le r_1且r_2>r_1 l2≤r1且r2>r1,此时 I 1 I_1 I1和 I 2 I_2 I2应该是交错的,我们也不需要新增芝麻,只需将 I 1 I_1 I1中的芝麻移动到 [ l 2 , r 1 ] [l_2,r_1] [l2,r1]中,这时我们需要抛弃 I 2 I_2 I2,保留 I 1 I_1 I1,而此时我们可以认为 I 1 = [ l 2 , r 1 ] I_1=[l_2,r_1] I1=[l2,r1],不过这无关紧要,因为 [ l 1 , r 1 ] 还是 [ l 2 , r 1 ] [l_1,r_1]还是[l_2,r_1] [l1,r1]还是[l2,r1]对于后续的区间 I 3 , I 4 , . . . I_3,I_4,... I3,I4,...来说根本无所谓,反正 l 3 ≥ l 2 l_3\ge l_2 l3≥l2正如 l 3 ≥ l 1 l_3\ge l_1 l3≥l1
对于以上三种情况,只有情况1需要新增芝麻粒,情况1和2需要抛弃 I 1 I_1 I1,而只有情况3我们需要抛弃 I 2 I_2 I2
代码
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
typedef struct Interval
{
double l;
double r;
}Interval;
bool comp(Interval a,Interval b)
{
return (a.l<b.l);
}
int main()
{
int n,d;
int index=0;
while(cin>>n>>d)
{
if(n==0 && d==0)
{
break;
}
index++;
cout<<"Case "<<index<<": ";
Interval a[n];
int x,y;
bool flag=false;
for(int i=0;i<n;i++)
{
cin>>x>>y;
if(y>d)
{
flag=true;
}
else
{
a[i].l=(double)x-(double)sqrt((double)(d*d-y*y));
a[i].r=(double)x+(double)sqrt((double)(d*d-y*y));
}
}
if(flag)
{
cout<<-1<<endl;
}
else
{
sort(a,a+n,comp);
int sum=1;
double r1=a[0].r;
for(int i=1;i<n;i++)
{
if(a[i].l>r1)
{
sum++;
r1=a[i].r;
}
else
{
if(a[i].r<=r1)
{
r1=a[i].r;
}
else
{
//nothing
}
}
}
cout<<sum<<endl;
}
}
return 0;
}