图形排版

题目描述

ac8d010ae046484993d95c6555f54e41.png

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 张图片按原顺序的排版高度最低,你能求出最低高度是多少么?

输入描述

2dc8866c160844a4a3ecec5adfad16ed.png

输出描述

一个整数,表示在删除掉某一张图片之后,排版高度最少能是多少。

输入输出样例

示例

输入

4 3
2 2
2 3
2 2

输出

2

运行限制

  • 最大运行时间:2s
  • 最大运行内存: 256M

总通过次数: 1291  |  总提交次数: 2444  |  通过率: 52.8%

难度: 困难   标签: 2017, 模拟, 省赛, 搜索

代码:

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

const int MX = 1e5 + 5; // 定义数组的最大大小

int M, N; // M: 最大宽度, N: 物品数量
int w[MX], h[MX], t[MX]; // w[]: 物品宽度数组, h[]: 物品高度数组, t[]: 动态规划辅助数组

// 尝试将第i个物品附加到当前布局中
void attach(int i, int &W, int &H) {
  if (W + w[i] > M) {
    // 如果加上物品后超出最大宽度M,则按比例调整高度
    H = max(H, static_cast<int>(ceil(1.0 * h[i] * (M - W) / w[i])));
  } else {
    // 否则直接更新高度
    H = max(H, h[i]);
  }
  W = min(M, W + w[i]); // 更新当前布局宽度
}

// 计算从第i个物品开始到结束的最小高度和
int calc(int i, int W, int H) {
  while (i < N && W < M) {
    attach(i, W, H); // 尝试将第i个物品附加到布局中
    i++;
  }
  return H + t[i]; // 返回加上从第i个物品开始的最小高度和
}

int main() {
  scanf("%d%d", &M, &N); // 输入最大宽度M和物品数量N
  for (int i = 0; i < N; i++) {
    scanf("%d%d", &w[i], &h[i]); // 依次输入每个物品的宽度和高度
  }

  // 计算动态规划数组t[]
  for (int i = N - 1; i >= 0; i--) {
    t[i] = calc(i, 0, 0); // 计算从第i个物品开始的最小高度和,存入t[i]
  }

  int res = t[0]; // 初始化结果为从第0个物品开始的最小高度和
  int tmp;
  int pre_h = 0;
  int W = 0, H = 0;

  // 动态规划求解最小总高度和
  for (int i = 0; i < N; i++) {
    tmp = calc(i + 1, W, H); // 从第i+1个物品开始的最小高度和
    res = min(res, pre_h + tmp); // 更新最小总高度和

    attach(i, W, H); // 尝试将第i个物品附加到当前布局中
    if (W == M) {
      pre_h += H; // 如果当前布局达到最大宽度M,则将当前高度添加到总高度中
      W = 0;
      H = 0;
    }
  }

  printf("%d\n", res); // 输出最小总高度和
  return 0;
}

 

 

  • 14
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值