课堂练习 最大值 原题链接+题解
题目可以去我的洛谷题库看: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;
}
心情舒畅。提示一下,洛谷上开的是二分的时间限制,暴力可能不过