修路 | ||||||
|
||||||
Description | ||||||
前段时间,某省发生干旱,B山区的居民缺乏生活用水,现在需要从A城市修一条通往B山区的路。假设有A城市通往B山区的路由m条连续的路段组成,现在将这m条路段承包给n个工程队(n ≤ m ≤ 300)。为了修路的便利,每个工程队只能分配到连续的若干条路段(当然也可能只分配到一条路段或未分配到路段)。假设每个工程队修路的效率一样,即每修长度为1的路段所需的时间为1。现在给出路段的数量m,工程队的数量n,以及m条路段的长度(这m条路段的长度是按照从A城市往B山区的方向依次给出,每条路段的长度均小于1000),需要你计算出修完整条路所需的最短的时间(即耗时最长的工程队所用的时间)。 |
||||||
Input | ||||||
第一行是测试样例的个数T ,接下来是T个测试样例,每个测试样例占2行,第一行是路段的数量m和工程队的数量n,第二行是m条路段的长度。 |
||||||
Output | ||||||
对于每个测试样例,输出修完整条路所需的最短的时间。 |
||||||
Sample Input | ||||||
2 4 3 100 200 300 400 9 4 250 100 150 400 550 200 50 700 300 |
||||||
Sample Output | ||||||
400 900 |
二分,写了很多次,最后总结一下所有路过的坑点
上下界:上界为总和,下界为最大值。
计数:如果初始为1,则不用考虑最后。如果初始为0,则考虑最后。
初始化:注意while内部的初始化!!!!!
#include<iostream>
#include<cstdio>
using namespace std;
#define INF 0x3f3f3f3f
long long a[100006];
int main()
{
int n,m,T;
cin>>T;
while(T--)
{
cin>>n>>m;
{
long long maxnum=0;
long long sum=0;
for(int i=1; i<=n; i++)
{
cin>>a[i];
maxnum=max(maxnum,a[i]);
sum+=a[i];
}
long long l=maxnum,r=sum;
long long now=0;
long long need=0;
while(l<=r)
{
now=0; ///两者初始化!!!!忘记很多次,坑了很多次,修路是心中的坑
need=0;
long long mid=(l+r)/2;
for(int i=1; i<=n; i++)
{
now+=a[i];
if(now>mid)
{
need++,now=a[i];
}
}
if(now)
need++;
if(need>m)
l=mid+1;
else
r=mid-1;
}
cout<<r+1<<endl;
}
}
}
其中,初始为0时(我自己常写的一种)
now=0;
need=0;
long long mid=(l+r)/2;
for(int i=1; i<=n; i++)
{
now+=a[i];
if(now>mid)
{
need++,now=a[i];
}
}
if(now)
need++;
初始化为1时(其他人博客常写,但是一直没注意区别,导致浪费了很多时间)
int temp = l[0];
int ans = 1;
for(int i=1;i<m;i++)
{
if(temp + l[i] >= mid)
{
ans++;
temp = l[i];
}
else
{
temp += l[i];
}
}
纪念一下,终于能彻底摆脱修路的坑了XD(希望是吧)