latex自然是广大研究人员最喜欢使用的科研论文排版工具之一。
月神想在iPhone 上查阅写好的paper,但是无赖iPhone 上没有月神喜欢使用的阅读软件,于是月神也希望像tex老爷爷Donald Knuth那样自己动手do it yourself一个。
在DIY这个阅读软件的过程中,月神碰到一个问题,已知iPhone屏幕的高为H,宽为W,若字体大小为S(假设为方形),则一行可放W / S(取整数部分)个文字,一屏最多可放H / S (取整数部分)行文字。
已知一篇paper有N个段落,每个段落的文字数目由a1, a2, a3,...., an表示,月神希望排版的页数不多于P页(一屏显示一页),那么月神最多可使用多大的字体呢?
1 <= W, H, ai <= 1000
1 <= P <= 1000000
输入描述:
每个测试用例的输入包含两行。 第一行输入N,P,H,W 第二行输入N个数a1,a2,a3,...,an表示每个段落的文字个数。 输出描述:
对于每个测试用例,输出最大允许的字符大小S
示例1
输入
1 10 4 3 10 2 10 4 3 10 10
输出
3 2
备注:
以上所有输入、输出均为整数。 且所有测试用例均保证有解。 两个段落之前不空行,并且段落顶格写。
这道题目一看就是典型的二分算法。
这题理解题意有一定难度,这里不用考虑段落前什么的。段落后的空行对应一个向上取整。这里计算的时候先计算所需要的行数,最后再计算所需要的页数。
这里要特别注意向上取整和向下取整的问题,可以使用ceil函数
同时,二分写的时候,最后可以比较left,和right,看看输出left还是输出right
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 10000;
int arr[N];
int n, P, H, W;
bool check(int mid) {
int line = 0;
int page = 0;
for (int i = 0; i < n; i++) {
// 先计算行数所需要的行数
line += ceil(1.0*arr[i] / floor(1.0*(W / mid))); // 总字数除以每一行的字数向上取整
// 再计算所需要的页数
}
page = ceil(1.0*line / floor(1.0*(H / mid))); // 总行数除以每一页的行数向上取整
//cout << line << endl;
//printf("%d\n", page);
return page <= P;
}
int main()
{
while (cin >> n >> P >> H >> W) {
for (int i = 0; i < n; i++) {
cin >> arr[i];
}
int left = 0, right = min(W,H);
while (left <= right) {
int mid = left + (right - left) / 2;
//cout << mid << endl;
if (check(mid)) {
left = mid + 1;
}
else {
right = mid - 1;
}
}
printf("%d\n", right);
}
}