题目:有 n 件刚洗完的衣服,其中第 i 件衣服上含有 ai 单位水分。

自然晾干的情况下,每件衣服每分钟可以减少 1 单位水分。

有一个可以使用的烘***,同一时间仅能容纳最多一件衣服。

在使用烘***的情况下,每件衣服每分钟可以减少 k 单位水分。

烘***每次使用的工作时间必须是整数分钟,不足 k 单位水分的衣服放入烘***,其包含水分最多降低至 0 ,而不会减为负值。

当衣服包含的水分变为 0 时,表示衣服已经干透了。

请你合理利用烘***,使得所有衣服干透所需的时间尽可能少。

输出所有衣服干透所需的最小可能分钟数。

输入格式: 第一行包含一个整数 n 。

第二行包含 n 个整数 a1,a2,…,an 。

第三行包含一个整数 k 。

输出格式 输出一个整数,表示所有衣服干透所需的最小可能分钟数。

数据范围 1≤n≤105 , 1≤ai≤109 , 1≤k≤109 。

思路:这是二分查找的应用,对于求最值问题的题,有暴力->二分查找->贪心->动态规划几种解法。其中二分查找要求该问题的结果与参数是单调(或突变)关系,像这道题就是随着时间(参数)不断变大,可以突然从不能完成任务,到完成任务。这就相当于已经排过序,利用二分查找(log n)的特性,可以缩短传统暴力枚举(n)的时间。

AC代码:

#include<iostream>
#include <cmath>
#include<algorithm>
using namespace std;
int a[100010];
int n;
int k;
bool check(int time)
{
    int chuitime=0;
    for (int i = 1; i <= n; i ++ )
    {
        if(a[i]<=time) {continue;}
        chuitime+=(a[i]-time+k-1-1)/(k-1);//ceil(x/y)=>(x+y-1)/y;
        if(chuitime>time) {return false;}//提前退出
    }
    return true;
}
int main()
{
    cin>>n;
    int maxx=0;
    for (int i = 1; i <= n; i ++ ) {cin>>a[i];maxx = max(maxx, a[i]);}
    cin>>k;
    if(k==1) {cout<<maxx;return 0;}//k-1=0,而分母不能为0
  //下面是二分查找,相当于找符合要求的第一个元素的类型
    int l=1,r=maxx,mid=(l+r)/2;
    while(l<r)
    {
        if(check(mid)) {r=mid;}
        else{l=mid+1;}
        mid=(l+r)/2;
    }
    cout<<l;
    return 0;
}