蓝桥杯 试题 算法提高 和谐宿舍

问题描述

  我的某室友学过素描,墙上有n张他的作品。这些作品都是宽度为1,高度不定的矩形,从左到右排成一排,且底边在同一水平线上。
  宿舍评比就要来了,为了及格,我们决定买不多于m块的矩形木板,把这些作品和谐掉。要求木板也从左到右排成一排,且底边与作品的底边在同一水平线上。
  在能够把所有作品和谐掉的前提下,我们希望最大的那块木板的面积最小,问最大木板的面积。

输入格式

  第一行两个数n和m,表示作品数和木板数;
  第二行n个数Hi,表示从左到右第i个作品的高度。

输出格式

  一行一个数ans,表示答案。

样例输入

5 2
4 2 3 5 4

样例输出

12

数据规模和约定

  对于30%的数据:1<=n,m<=10;
  对于100%的数据:1<=n,m<=100000,1<=Hi<=10000。

#include <bits/stdc++.h>
using namespace std;
long long l;
long long r;
long long n, m;
long long *a;
long long check(long long mid)
{

    long long wrap = 0;
    // long long sum = 0;

    for (long long i = 0; i < n;)
    {
        wrap += 1; // 包裹数加一
        long long length = 1;
        long long ma = a[i];
        while (1)
        {
            long long maxTemp = ma;
            ma = max(ma, a[i + length]);
            if (ma * (length + 1) <= mid && i + length < n) // 不超过
            {
                // 还要判断是否超索引了
                length++;
            }
            else
            {
                i += length;
                break;
            }
        }

        // cout << i << " " << a[i] << " " << sum << " " << mid << endl;
    }
    if (wrap <= m)
        return 1;
    else
        return 0;
}
int main()
{

    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    cin >> n >> m;
    a = new long long[n];
    long long ma = -1;

    for (long long i = 0; i < n; i++)
    {
        cin >> a[i];
        ma = max(ma, a[i]);
    }
    long long sum = ma * n;
    l = ma;
    r = sum;
    long long ans = 0;
    while (l <= r) // 二分
    {
        long long mid = (l + r) / 2;
        // cout << l << " " << r << " " << mid << endl;
        if (check(mid)) // 检查是否满足条件
        {
            ans = mid;
            r = mid - 1; // 缩小范围继续二分
        }
        else
            l = mid + 1; // 继续向右半段二分
    }

    cout << ans;
    delete a;
    return 0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值