题解:ABC319D - Minimum Width
·题目
链接:Atcoder。
链接:洛谷。
·难度
算法难度:B。
思维难度:A。
调码难度:A。
综合评价:普及/提高-。
·算法
二分答案+贪心验证。
·思路
由于满足单调性,我们二分最后的宽度,当然范围是“每个单词长度的最大值”到“一个很大的数(设成1e15即可)”。我们只需要用贪心验证每个mid的宽度是否能够在m行之内装下所有单词即可。
·代价
O(n*log(一个数)),反正肯定够用。
·细节
贪心验证用单独函数“calc”实现。
·代码
#include<bits/stdc++.h>
#define N 220000
using namespace std;
long long a[N]={},m=0,mx=0,n=0;
bool calc(long long num);
int main(){
scanf("%lld%lld",&n,&m);
for(long long i=1;i<=n;i++){
scanf("%lld",&a[i]);
mx=max(mx,a[i]);
}
//输入,并找到单词长度最大值
long long l=mx-1,r=1e15+1;
//确定双端便边界,开始二分
while(l+1<r){
long long mid=(l+r)/2;
if(calc(mid)==false){
l=mid;
}else{
r=mid;
}
}
printf("%lld\n",r);
//输出答案r
return 0;
}
bool calc(long long num){
long long now=1,sum=-1;
//now为当前用到第几行,sum表示用到第now行的第几列
//初始值是为了把第一个单词前面的空格磨平
for(long long i=1;i<=n;i++){
if(sum+1+a[i]<=num){
sum=sum+1+a[i];
//当前行能在放就放
}else{
sum=a[i];
now++;
//放不了就另起一行
}
}
if(sum==-1){
now--;
}
//把初始值的误差过滤掉
if(now<=m){
return true;
}
//符合条件返回true
return false;
//否则返回false
}
·注意
二分边界别设错了,否则会WA。