题解:P15007 [UOI 2019 II Stage] 草坪
Forever_Rain · · 题解
分析
我们有一个长度为
目标是使得草坪的每个部分至少被修剪过一次,求所需的最短时间。
思路
最小区间覆盖
问题等价于用最少的长度为
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,k;
cin>>n>>k;
cout<<(n+k-1)/k;
return 0;
}
拿到了
问题:如果两次修剪的区间有重叠,那么第二次修剪必须等到第一次修剪后才能进行,否则第二次修剪时重叠部分还没有草。
考虑重新生长的影响
如果两次修剪的区间没有重叠,那么它们可以连续进行(后一次在前一次结束后立即开始)。
如果两次修剪的区间有重叠,那么后一次修剪必须在前一次修剪结束至少1小时后才能开始(因为草需要时间重新生长)。由于每次修剪耗时1小时,这意味着两次修剪的开始时间至少相差2小时。
那么只需选择若干个长度为
设使用了
如果我们可以将这些区间排列成一个序列,使得序列中相邻的区间都没有重叠,那么这些区间就可以连续进行,总时间就是
因此,我们希望使用最少的区间数
当
当
-
如果
n = 2k ,我们可以选择两个互不重叠的区间(如[1, k] 和[k+1, 2k] ),连续进行,总时间为2小时。 -
如果
n < 2k ,则两个区间必然重叠,且无法避免相邻重叠(因为只有两个区间),因此总时间为2 + 1 = 3 小时(第一个区间1小时,等待1小时让草重新生长,第二个区间1小时)。
当
那么有普遍规律:若
代码
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,k;
cin>>n>>k;
int m=(n+k-1)/k;
if(m==1)cout<<1;
else if(m==2&&n<2*k)cout<<3;
else cout<<m;
return 0;
}