题目描述
小e要把 本规格相同的书放进书架里,对于每一本书,他可以横着放也可以竖着放(不能斜着放)。
书的宽度为 ,高度为 ,书架的高度为 ,意味着如果你横着放,每 长度的书架最多叠 本,如果竖着放,每 长度的书架可以放一本书(竖着放不能叠起来,且书的高度要小于等于书架高度)。
注意:你不能在横着放的书上面再竖着放,也不能在竖着放的书上方横着放书。
请问书架的至少要多长,才能放下所有的书?
输入格式
第一行一个整数 表示测试样例个数,满足条件:。
对于每个样例,一行三个整数表示 , , ,满足条件:。
输出格式
对于每个样例,在一行输出结果(书架的最小长度)后换行。
样例
输入样例1
2
6 4 5
4 3 2
输出样例1
5
6
样例解释
第一个样例,前面 本书横着叠放,长度为 ,最后一本书竖着放,总长度为 。
第二个样例,书不能竖着放,必须全部横着放,总长度为 。
思路
在主函数中,首先读取测试用例的数量。对于每个测试用例,再读取三个整数,分别代表书的数量,书的高度,以及书架的高度。
接着,初始化了两个变量,代表二分查找的左右边界。在进行二分查找的过程中,目标是找到一个长度,使得check(mid)函数返回true,且这个长度尽可能小。
check(mid)函数的作用是检查给定的长度是否满足条件。首先,计算如果书横放在书架上,最多可以放多少本书。然后,如果书架的高度小于等于横放书的数量,还会尝试纵放一些书。最后,函数返回的是这个总数是否大于等于书的数量,即是否有足够的空间来放下所有的书。
在主函数的二分查找过程中,每次迭代都会计算中点,然后使用check(mid)函数来检查这个中点是否满足条件。如果满足条件,那么就将右边界移动到这个中点,因为要找到的是满足条件的最小的值;否则,将左边界移动到这个中点。这个过程会一直重复,直到左边界和右边界之间没有其他的值为止。
最后,输出满足条件的最小值,也就是右边界的值,这就是满足条件的最小书架长度。
AC代码
#include <iostream>
#define ll long long
#define AUTHOR "HEX9CF"
using namespace std;
int m;
int n, h, t;
bool check(ll mid) {
// 横放
ll cnt = (mid / h) * t;
if (h <= t) {
// 竖放
cnt += mid % h;
}
return cnt >= n;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> m;
for (int i = 1; i <= m; i++) {
cin >> n >> h >> t;
ll l = 0;
ll r = 1e16;
while (l + 1 < r) {
ll mid = (l + r) >> 1;
if (check(mid)) {
r = mid;
} else {
l = mid;
}
}
cout << r << endl;
}
return 0;
}