课堂练习 最大值 原题链接+题解

题目可以去我的洛谷题库看:https://www.luogu.com.cn/problem/U412348(带数据,真难出)

题解

考虑两种解题方式。

由于题目范围较小,可以 check+暴力,如果范围大一点,可以 check+二分答案。

先讲 check 函数,小学四年级数学书说了,这种问题也被它叫做“铺地砖”问题,计算剪出的正方形数量的方法是:

\[\lfloor长\div边长\rfloor \times \lfloor 宽 \div边长\rfloor \]

所以check函数的写法是:

int check(int x){
  int ans = 0;
  for (auto i : sv){
    ans += (i.w / x) * (i.h / x);
  }
  return ans;
}

直接写 int,懒得 bool 了。我就不写暴力了,写二分。

二分的话要注意,区间是 \(\textcolor{red}{[}1, maxn\textcolor{red}{]}\),对于无解判定的话,只需要考虑 \(\sum w_ih_i\) 是否大于等于 \(k\),小于输出 -1

代码:

#include <bits/stdc++.h>
using namespace std;

struct paper{
  int w, h;
};

vector <paper> sv;

int check(int x){
  int ans = 0;
  for (auto i : sv){
    ans += (i.w / x) * (i.h / x);
  }
  return ans;
}

int main(){
  int n, k, maxn = INT_MIN, sum = 0;
  cin >> n >> k;
  
  for (int i = 0; i < n; i ++){
    int a, b;
    cin >> a >> b;
    sv.push_back({a, b});
    sum += a * b;
    maxn = max(maxn, min(a, b));
  }

  if (sum < k){
    cout << -1;
    return 0;
  }

  int l = 0, r = 1001;
  while (l < r - 1){
    int ret = check((l + r) / 2);
    if (ret < k){
      r = (l + r) / 2;
    }else{
      l = (l + r) / 2;
    }
  }
  if (check(l) == k) cout << l;
  else cout << r;
}

心情舒畅。提示一下,洛谷上开的是二分的时间限制,暴力可能不过

posted @ 2024-03-09 15:08  lym12_ovo  阅读(28)  评论(0编辑  收藏  举报