白书上很水很水的贪心,军训太久没做题,看了老半天想不出选取的贪心策略。。。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn=100010;
const int inf=0x3f3f3f3f;
int x[maxn];
int r,n;
int main()
{
while(cin>>r>>n&&(r!=-1||n!=-1)){
for(int i=0;i<n;i++){
cin>>x[i];
}
sort(x,x+n);
x[n]=inf;//最后一个点之后的点不存在,防止超出数组
int ans=0;
int i=0;
while(i<n){
int pos=i;
while(1){
if(x[pos+1]>x[i]+r){ //在x[i]+r范围内找最远的点标记
ans++;
i=pos;
break;
}
pos++;
}
while(x[i]<=x[pos]+r) i++; //标记之后找x[i]+r以外的第一个点
}
cout<<ans<<endl;
}
return 0;
}
我开始想复杂了,以为是整成区间贪心,然后根据某种策略,选相交最多的部分。
结果看题解,只是从左开始选,每步选最优,也就是最水的贪心。。。
例如对最左的点,在他r范围以内选取一个点标记,显然,如果存在标记第i个点用来覆盖他,那么从1~i-1之间的点必然可以被这个标记点覆盖,那么如果范围内存在i+1个点,显然可以覆盖i能覆盖的点,并且右侧可以到达更远的地方,明显更优。
故选择r范围内离得最远的点。