修剪树木
题目描述:
学校的环境优美,景色宜人,种植了很多绿化树。最近天气预报显示台风即将到来,为应对台风天气,学校近日组织开展专项绿化修剪工作,排查绿化树木存在的安全隐患,
修剪过长或枯萎树枝。现在已知总共需要修剪的树木数量
n
n
n(树木的序号为
1...
n
1...n
1...n,按相邻的次序排列)以及每棵树修剪的耗费时间,学校打算安排m位工作人员来修剪树木,
为了提高工作效率避免来回跑动,每位工作人员安排修剪的树木一定是相邻的。为了保证能在台风到来前完成工作,负责人需要知道安排m位工作人员去修剪树木,最快需要多少时间就能完成修剪。
输入格式
Line 1: 两个用空格分开的整数n和m,分别表示需要修剪的树木总数和派出的工作人员数目,
1
≤
m
≤
n
≤
100
,
000
1≤m≤n≤100,000
1≤m≤n≤100,000
Lines 2…n+1: 第 i+1 行包含1个整数,表示修剪第i棵树需要的时间耗费
t
i
(
1
≤
t
i
≤
10
,
000
)
ti(1 ≤ ti ≤10,000)
ti(1≤ti≤10,000),这n棵树按照相邻的次序排列
输出格式
Line 1: 输出最快能完成修剪所有树木的时间
输入样例
7 5
100
400
300
100
500
101
400
输出样例
500
提示
派出5个工作人员,第1个工作人员修剪第1、2两棵树(耗费时间为500),第2个工作人员修剪第3、4两棵树(耗费时间为400),第3个工作人员修剪第5棵树(耗费时间为500),
第4个工作人员修剪第6棵树(耗费时间为101),第5个工作人员修剪第7棵树(耗费时间为400),由于工作人员是同时工作的,所以最终总耗费时间500则可完成修剪任务.
思路:二分查找
时间复杂度:O(Nlogm)
首先通过枚举可能的时间并判断是否符合条件,然后来确定本题最快能完成修剪所有树木的时间。但是一个一个枚举查找,时间复杂度太高,所以要优化。可以用二分查找
的方法来优化,使得查找时间从O(N)-->O(logN)
。其中N表示修建数目的时间范围本题的ti
修建时间是
t
i
(
1
≤
t
i
≤
10
,
000
)
ti(1 ≤ ti ≤10,000)
ti(1≤ti≤10,000)。
其次就是二分查找
的判断条件check函数
了。check函数通过遍历工人,看在满足枚举的时间mid
内能够最多修建多少颗树,如果修建的树的数量多于n
棵,则表示满足条件,返回true,否则返回false。
不清楚二分查找或者二分查找不熟的,可以点击这个链接–>二分查找例题
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=1e5+10;
int n,m;
int a[N];
bool check(int mid)//mid表示枚举的可能的时间。
{
int j=1;
for(int i=1;i<=m;i++)
{
int t=mid;//把开始剩余的时间设成mid
while(t>=a[j])//如果剩余的大于遍历到的那棵树的修剪需要的时间,就修剪该树。
{
t-=a[j];
j++;
}
if(j>n+1)//如果修剪的树木的数量大于树木的总数,就表明成立
{
return true;
}
}
return false;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
int l=1,r=1e9;
while(l<r)
{
int mid = (l + r) / 2;
if(check(mid)) r=mid;
else l=mid+1;
}
cout<<l;
return 0;
}