洛谷P2440 木材加工 題解

Trubiacy發表於2024-08-24

這是我找到的一篇很久之前為了讓我更好理解二分寫的詳細題解

題目連結

code:

#include <bits/stdc++.h>
#define int long long
#define MAXN 0x3f3f3f3f3f3f3f3f
#define MINN -0x3f3f3f3f3f3f3f3f
#define Mirai ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
using namespace std;

const int N=1e5+29;
int n,k,maxn;
int a[N];

bool check(int x){//x表示小段木頭的長度
    int ans=0;
    for(int i=1;i<=n;i++) ans+=a[i]/x;//列舉每根原木,將能從這根原木中切割出長度為x的小段木頭的數量累加到ans中
    return ans>=k;//這裡取了等號給l
}
int binary(){
    int l=0,r=maxn+1;//這裡l最好從0開始,r從maxn+1開始,避免出鍋
    while(l+1<r){//老師講的最原始的方法【也是我覺得最好理解的
        int mid=l+r>>1;
        if(check(mid)) l=mid;
        else r=mid;
    }
    return l;//因為等號給了l,所以答案儲存在l裡
}

signed main(){
    cin>>n>>k;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        maxn=max(maxn,a[i]);//用於確定二分中r的初始值
    }
    cout<<binary();
    return 0;
}

注意事項:

注意二分中=給的物件,若 \(l\) 取到=,答案儲存在 \(l\) 中,反之則在 \(r\) 中。

二分中建議初始化 \(l=0,r=maxn+1\) 避免出現一些難調的bug

如果擔心不能切割的情況,即答案為 \(0\) 時會出錯,可在main函式中特判:

    int sum=0;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        sum+=a[i];
    }
    if(sum<k){
        cout<<0;
        return 0;
    }

相關文章