二分查找
//二分法的标准写法
while (L <= R)
{
if () L = mid;
else R = mid;
}
因为a/b是向下取整,所以while(L<R)为二分判断标准时,循环会跳不出,因为当R=L+1时,mid=(L+R)/2=L,会变成死循环。
题目
- 修路HRBUST-1039
- 解题分析:二分求解,分析时间的范围
最大时间:整条路由一个队来修
最短时间:修整路段中最长的一段路所用的时间,即耗时最长的工程队所用的时间
难点:
判断遍历的路段的长度和前一个相加是否小于猜测的构造队伍最少花的时间
如果是就继续加
如果不是就从这个点重新累加
得到如果按这个预期算总共要用多少支队伍
如果得到的队伍数比给出的队伍数多了就代表预期短了,则扩大左区域,少了就代表比预期长了,则减小右区域
#include <iostream>
#include <algorithm>
#include <cstring>
#include <stdio.h>
#define MAXSIZE 305
using namespace std; //使用名称空间std
int road[MAXSIZE];
int main()
{
int find(int L, int R, int m);
int n, m;
int T;
int L = 0, R = 0; //二分下界L为最长路段,上界R为总长
int ans = 0;
int num;
int max;
scanf("%d", &T);
while (T--)
{
num = 0;
L = 0;
R = 0;
ans = 0;
memset(road, 0, sizeof(road));
scanf("%d%d", &m, &n);
for (int i = 0;i < m;i++)
{
scanf("%d", &road[i]);
R += road[i];
L = L < road[i] ? road[i] : L;
}
//获取二分下界和二分上界
while (L <= R)
{//二分查找
num = find(L, R, m); //分配的施工队数
if (num <= n)
{//二分估计的时间得到的施工队数较少,减小区间右侧
R = (L + R) / 2 - 1; //用max进行优化
}
else
{//二分估计时间较小,减小左区间
L = (L + R) / 2 + 1;
}
}
printf("%d\n", L);
}
return 0;
}
int find(int L, int R, int m)
{//返回估计对应的施工队数
int mid = (L + R) / 2;
int cnt = 0;
int res = 0;
int i = 0;
while (i < m)
{
if (res + road[i] <= mid)
{
res += road[i];
i++;
}
else
{
res = 0;
cnt++;
}
}
cnt++;
return cnt;
}