题目: 传送门
题意: 在一个长度为n的直线上有几个加热器(用‘1’标记),开启一个加热器可以让左右两边一定长度的区间内物品都预热,求最少要开启几个加热器才能让整段直线都能预热。(如果不能则输出"-1")。
思路: 一道很明显的区间覆盖题,我们可以从贪心方面着手。如果当前1-i区间已经完全被覆盖了,则下一个最优加热器应该接近距刚好能覆盖i+1的点的加热器,如果没有则往左找最近的一个,如果无法找到则表示我们无法覆盖i+1,即我们无法覆盖整段直线,如果找到了,则更下已经完全被覆盖的区间,再进行上述操作.
ac代码:
queue<int> q;
int a[20000];
int main() {
long long n,r;
cin>>n>>r;
long long haves= 0;
long long now = r-1;//当前的最优覆盖点
long long limit = -1;//当前已经完全覆盖的右区间
for(int i=0;i<n;i++) {
cin>>a[i];
if(a[i]==1) q.push(i); // 把加入其放进队列
}
while(!q.empty()) {
int i = q.front();
q.pop();
if(limit >= n-1) break; //如果已经覆盖整段直线
if(i > now) {
cout<<"-1"<<endl;
return 0;
}
else {
if(!q.empty()) {
if(q.front()<=now) {//表示下一个是更优选项
continue;
}
else {
haves++;
now = i+2*r-1;
limit = i+r-1;
}
}
else {
haves ++;
now = i+2*r-1;
limit = i+r-1;
}
}
}
if(limit<n-1) cout<<"-1"<<endl;
else cout<<haves<<endl;
return 0;
}