0
点赞
收藏
分享

微信扫一扫

codeforce 551C

Yaphets_巍 2022-09-19 阅读 45


题意:有n堆箱子,m个人,每个人只能般一个箱子,每次搬箱子的时间为1s,每走一步,花1s时间
题解:该题用了二分的思想
First.step:先确定时间的最大值与最小值,最小值就是没有箱子,时间就等于走的步数+1,令最小时间为MinT=step+1,最大时间MaxT=MinT+箱子的数量,这个最大时间假设的是仅有一个人的情况,现在就找到区间了[MinT,MaxT],我们所要求的最短时间就在这个区间中

Second.step:这里我们要构造一个判断的函数,判断我们的在[MinT,MaxT]的时间是大了还是小了,如果大了,就将上边界MaxT更新,小了就将下边界MinT更新。知道找到刚刚好的值,这个值就是最小时间

AC代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define maxn 100005
ll a[maxn];
int n,m,k;
//该函数逆推,在知道时间后,推在给定人数下能否完成,能完成缩小时间范围,完不成扩大时间范围
bool judge_time(ll x)
{
ll sum=0;//代表搬箱子需要的时间
ll ren_s=m;//代表人数
for(int i=1;i<=k;i++)
{
sum+=a[i];
while(sum+i>=x)
{
ren_s--;
sum-=(x-i);//x代表给定的时间,x-i代表在给定的时间内,一个人搬箱子的时间
if(ren_s<0)
return 0;
}
}
if(ren_s==0)//人数为零,箱子不为0,肯定在任何时间都不可能
{
if(sum>0)
return false;
}
return true;
}
int main()
{ ll total;
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
if(a[i])
k=i;
total+=a[i];
}
ll l=k+1;
ll r=l+total,mid,ans=0;
while(l<=r)//二分操作
{
mid=(l+r)/2;
if(judge_time(mid))//mid是我们区间的时间,操作到最后的答案就是我们所需的答案
{ ans=mid;
r=mid-1;
}
else
l=mid+1;
}
printf("%lld\n",ans);
}


举报

相关推荐

0 条评论