先贴个题目:
以及原题链接: 112. 雷达设备 - AcWing题库https://www.acwing.com/problem/content/114/
这题如果直接枚举点肯定是不行的,但可以把每个小岛的可能雷达设置点抽象成x轴上的线段进行贪心,我们的选点尽量选在线段的重合处即可保证数量最少,这里有两个思路的小不同,在对线段进行排序的时候是根据左端点排序还是右端点排序?
我们注意到如果要设立一个新的雷达点,应该尽量在该线段的右端,那如果根据左端点排序,可能出现左端点很小右端点很大的情况,导致这个右端点其实不是最优解,所以依据右端点排序,枚举后判断左端点是否比他小即可,如果想根据左端点排序,每次应该取两次比较的线段的右端最小值作为设置雷达的判断。
代码如下:
依据左端点排序:
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
typedef pair<double,double> PDD;
#define x first
#define y second
const int N=1010;
PDD list[N];
int main()
{
int n,d;
cin>>n>>d;
bool sign=true;
for(int i=0;i<n;++i)
{
int x,y;
scanf("%d%d",&x,&y);
if(y>d)
{
sign=false;
break;
}
double dx=sqrt(d*d-y*y);
list[i].x=x-dx;
list[i].y=x+dx;
}
if(!sign)
{
cout<<"-1";
return 0;
}
sort(list,list+n);
// for(int i=0;i<n;++i)
//printf("%lf %lf\n",list[i].x,list[i].y);
double s=list[0].y;
int ans=1;
for(int i=1;i<n;++i)
{
if(s>=list[i].x)
{
s=min(s,list[i].y);
}
else
{
//cout<<ans<<" "<<s<<" "<<list[i].y<<endl;
ans++;
s=list[i].y;
}
}
cout<<ans;
return 0;
}
依据右端点排序:
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
typedef pair<double, double> PDD;
#define l second
#define r first
const int N = 1010;
PDD list[N];
int main()
{
int n, d;
cin >> n >> d;
bool sign = true;
for (int i = 0; i < n; ++i)
{
int x, y;
scanf("%d%d", &x, &y);
if (y > d)
{
sign = false;
break;
}
double dx = sqrt(d * d - y * y);
list[i].l = x - dx;
list[i].r = x + dx;
}
if (!sign)
{
cout << -1;
return 0;
}
sort(list, list + n);
double s = list[0].r;
int ans = 1;
for (int i = 1; i < n; ++i)
{
if (s >= list[i].l)
continue;
else
{
ans++;
s = list[i].r;
}
}
cout << ans;
return 0;
}
by————2024.4.9刷题记录