1、问题描述
小明需要在一篇文档中加入 N 张图片,其中第 i 张图片的宽度是 Wi,高度是 Hi。
假设纸张的宽度是 M,小明使用的文档编辑工具会用以下方式对图片进行自动排版:
1. 该工具会按照图片顺序,在宽度 M 以内,将尽可能多的图片排在一行。该行的高度是行内最高的图片的高度。例如在 M=10 的纸张上依次打印 3x4, 2x2, 3x3 三张图片,则效果如下图所示,这一行高度为4。(分割线以上为列标尺,分割线以下为排版区域;数字组成的矩形为第x张图片占用的版面)
0123456789
----------
111
111 333
11122333
11122333
2. 如果当前行剩余宽度大于0,并且小于下一张图片,则下一张图片会按比例缩放到宽度为当前行剩余宽度(高度向上取整),然后放入当前行。例如再放入一张4x9的图片,由于剩余宽度是2,这张图片会被压缩到2x5,再被放入第一行的末尾。此时该行高度为5:
0123456789
----------
44
111 44
111 33344
1112233344
1112233344
3. 如果当前行剩余宽度为0,该工具会从下一行开始继续对剩余的图片进行排版,直到所有图片都处理完毕。此时所有行的总高度和就是这 N 张图片的排版高度。例如再放入11x1, 5x5, 3x4 的图片后,效果如下图所示,总高度为11:
0123456789
----------
44
111 44
111 33344
1112233344
1112233344
5555555555
66666
66666777
66666777
66666777
66666777
现在由于排版高度过高,图片的先后顺序也不能改变,小明只好从 N 张图片中选择一张删除掉以降低总高度。他希望剩余N-1张图片按原顺序的排版高度最低,你能求出最低高度是多少么?
样例输入
4 3
2 2
2 3
2 2
样例输出
2
2、代码实现
import java.util.Scanner;
public class Main{
//当前排版的宽和高
static int width;
static int height;
//图片个数
static int pictures;
//存储图片的尺寸
static int[][] size;
//最小的高度
static int ans = Integer.MAX_VALUE;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
width = scanner.nextInt();
pictures = scanner.nextInt();
size = new int[pictures][2];
for(int i = 0;i < pictures;i++) {
size[i][0] = scanner.nextInt();
size[i][1] = scanner.nextInt();
}
for(int i = 0;i < pictures;i++) {
//去除第i个图形的高度,找到最小的
int t = put(i);
if(t < ans) {
ans = t;
}
}
System.out.println(ans);
}
public static int put(int n) {
//总的高度
int h = 0;
//当前行占用的高度
int high = 0;
//当前行占用的宽度
int w = width;
for(int i = 0;i < pictures;i++) {
//不使用第n个图片
if(i == n) {
continue;
}
// 当前宽度可以放下这张图片
if(w > size[i][0]) {
//获取剩余的宽度
w -= size[i][0];
//获取占用的高度
if(size[i][1] > high) {
high = size[i][1];
}
}else {
//当前宽度不足以放下这张照片,需要调整这张图片的大小
int adjust = (int) Math.ceil(1.0 * size[i][1] * w / size[i][0]);
//调整占用的高度
if(adjust > high) {
high = adjust;
}
//程序执行到此处,说明这张图片是这行的最后一张,该换行了
h += high;
high = 0;
w = width;
}
}
// 当high等于0时表示最后一行是占满的
// 当high不等于0时表示最后一行未满,且没有加入到总的高度中,所以要加上
return high == 0 ? h : h + high;
}
}