题解:ABC319D - Minimum Width

题解: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。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值