蓝桥杯算法题-图形排版

题目描述

小明需要在一篇文档中加入 N 张图片,其中第 i 张图片的宽度是 Wi,高度是 Hi。
  假设纸张的宽度是 M,小明使用的文档编辑工具会用以下方式对图片进行自动排版:

1. 该工具会按照图片顺序,在宽度 M 以内,将尽可能多的图片排在一行。该行的高度是行内最高的图片的高度。例如在 M=10 的纸张上依次打印 3x4, 2x2, 3x3 三张图片,则效果如下图所示,这一行高度为4。(分割线以上为列标尺,分割线以下为排版区域;数字组成的矩形为第x张图片占用的版面)
 
2. 如果当前行剩余宽度大于0,并且小于下一张图片,则下一张图片会按比例缩放到宽度为当前行剩余宽度(高度向上取整),然后放入当前行。例如再放入一张4x9的图片,由于剩余宽度是2,这张图片会被压缩到2x5,再被放入第一行的末尾。此时该行高度为5:

3. 如果当前行剩余宽度为0,该工具会从下一行开始继续对剩余的图片进行排版,直到所有图片都处理完毕。此时所有行的总高度和就是这 N 张图片的排版高度。例如再放入11x1, 5x5, 3x4 的图片后,效果如下图所示,总高度为11:


现在由于排版高度过高,图片的先后顺序也不能改变,小明只好从 N 张图片中选择一张删除掉以降低总高度。他希望剩余N-1张图片按原顺序的排版高度最低,你能求出最低高度是多少么?

输入:
第一行包含两个整数 M 和 N,分别表示纸张宽度和图片的数量。
  接下来 N 行,每行2个整数Wi, Hi,表示第 i 个图大小为 Wi*Hi。

对于30%的数据,满足1<=N<=1000
  对于100%的数据,满足1<=N<=100000,1<=M, Wi, Hi<=100

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

样例输入1:
4 3
2 2
2 3
2 2
样例输出1:
2
 

 思路:要删去一张图片,使高度最小,无非是遍历N张图片,判断第i个图片不选是否拥有更小的高度。

可以分割一下状态,例如第i行中图片j,判断不选图片j的高度,可以由三个状态组成:

①前i-1行的总高度,这是固定的,在遍历过程就可以知道;

②i+1行以后的总高度,这个要怎么得到呢,可以知道,i+1行开头肯定是新的照片k,我从那张照片k开始遍历到最后一张照片,所得的高度一定是确定的,可以设置一个数组t[i]保留i照片以及以后的高度。

③此时不选j,第i行的高度,想要求这个可以定义一个calc函数,实现向行中添加图片,直到添加完全部图片或者宽度已达最大,求出该行的高度(再加上t[i]就成了第i行以及以后所有行的总高度),为了实现calc函数,还得定义一个solve函数,solve函数的目的是判断加了一张图片,该行的宽度和高度变化。

很明显用了动态规划的思想,他有状态转移关系,问题被细分为了多个子问题,把处理全部细分为了处理行。

这种方法适用于一些题目,题目中总体只修改了部分结构,只需要处理那部分被修改的状态,其余的部分可以通过处理得到,视为常量。

代码如下:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int m,n,h[N],w[N],t[N];
void solve(int i,int& W,int& H){if(W+w[i]<=m){ H=max(H,h[i]); }else{H=max(H,(h[i]*(m-W)+w[i]-1)/w[i]);}W=min(m,W+w[i]);
} 
int calc(int i,int W,int H){while(i<n&&W<m)solve(i++,W,H); return H+t[i];
}
int main(){cin>>m>>n;for(int i=0;i<n;i++)cin>>w[i]>>h[i];for(int i=n-1;i>=0;i--)t[i]=calc(i,0,0);int res=t[0],pre_h=0,W=0,H=0;for(int i=0;i<n;i++){int tmp=calc(i+1,W,H);res=min(res,pre_h+tmp);solve(i,W,H);if(W==m)pre_h+=H,W=0,H=0;} cout<<res<<endl;
} 

加了注释后: 

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int m,n,h[N],w[N],t[N];//m为每行最大宽度,n为图片数量,h为每张图片对应高度,w为每张图片对应宽度,t[i]为以i图片为开始,与他以后所有的图片组合,形成的最小高度(一定是以i为行头开始)
void solve(int i,int& W,int& H){//找出加入i元素后,该行的高度和宽度所发生的变化 if(W+w[i]<=m){//没超出最大宽度 H=max(H,h[i]); }else{H=max(H,(h[i]*(m-W)+w[i]-1)/w[i]);//为什么要加w[i]-1,因为他要向上取整,所以要加一个小数,即(w[i]-1)/w[i]}W=min(m,W+w[i]);
} 
int calc(int i,int W,int H){//求出加入i以及他后边所有图片后,总高度的变化 while(i<n&&W<m)solve(i++,W,H);//只要算一行的,另起一行的可以直接由t[i]得到 return H+t[i];//为什么这里是H+t[i],因为之前的一行可能已经有照片了,我先填满那一行,拿到那一行的高度即H,然后之后的元素就另起一行了,对应t[i],所以t[i]是需要预处理的,所以总的高度为H+t[i] 
}
int main(){cin>>m>>n;for(int i=0;i<n;i++)cin>>w[i]>>h[i];for(int i=n-1;i>=0;i--)t[i]=calc(i,0,0);//W=0,H=0,说明要求的是以i照片开头的,与它以后所有的图片组合形成的最小高度,预处理阶段,不预处理,以后可能有重复的求解过程int res=t[0],pre_h=0,W=0,H=0;//res先取t[0],是代表所有图片都取了后它的高度, pre_h为 之前已经统计了的行的高度,正在统计的不算 for(int i=0;i<n;i++){int tmp=calc(i+1,W,H);//计算出加入i+1以及之后的所有图片后,总高度的变化,不包括i,这就对应了删除一张图片的思想 res=min(res,pre_h+tmp);//前者为之前统计出的最小高度,后者为不要i照片的最小高度 solve(i,W,H);//加入i照片if(W==m)pre_h+=H,W=0,H=0;//此时已经充满一行,那就得另起一行了,所以pre_h要+H,H和W要清零 } cout<<res<<endl;
} 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/579260.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于java高校社团招新系统设计与实现

摘要 &#xff1a;大学学生社团的不断壮大发展&#xff0c;让对社团的招新管理越来越重要&#xff0c;如何高效的管理社团&#xff0c;促进社团有效的运行和发展变得尤为关键。学生社团在学生的成长发展过程中有着一定的积极作用&#xff0c;要发挥好社团的优势&#xff0c;管…

商品数据化运营---初步整理

商品数据化运营是指利用数据分析技术来优化商品的销售、管理和推广过程。这种方法结合了数据科学、商业智能、市场分析和消费者行为研究等多个领域的技术和理论&#xff0c;旨在通过分析大量的商品和销售数据来提高商品的市场表现和企业的利润。 以下是商品数据化运营的一些关…

哪里脏扫哪里,脏污识别将成扫地机器人下一个“卷”点?

让“人工式”清洁成为可能。 同质化竞争中的下一个“卷”点&#xff1f; 对于扫地机器人而言&#xff0c;脏污识别并非是个新概念&#xff0c;从2022年开始就有厂商提出&#xff0c;只是相较于其它方面的“内卷”&#xff0c;厂商们最初对它的重视程度并不高&#xff0c;目前脏…

软考103-上午题-【结构化开发】-模块独立

一、命题特点 考试类型&#xff1a; 选择题&#xff08;3~9分&#xff09;综合分系题&#xff08;数据流图【试题一】&#xff0c;15分&#xff09; 二、系统设计的基本原理 1、抽象 2、模块化 将一个待开发的软件分解为若干个小的简单部分——模块。 每个模块可以独立的开…

登录者个人信息查询

目录 &#x1f95e;1.vo层描述 &#x1f37f;2..vo层创建 &#x1f32d;3.编写controller层 &#x1f953;4.service层 &#x1f9c2;5.测试 1.vo层描述 Spring Boot项目中的实体类通常用于映射数据库表&#xff0c;包含了业务对象的所有属性。然而&#xff0c;前端或其…

QT 最近使用的项目配置文件

目录 1 QT 最近使用的项目配置文件所在路径 2 QtCreator.ini 1 QT 最近使用的项目配置文件所在路径 C:\Users\your username\AppData\Roaming\QtProject QtCreator.ini最好先备份一份 2 QtCreator.ini ProjectExplorer 下面的 RecentProjects\FileNames RecentProjects\…

【AI】命令行调用大模型

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 【AI】命令行调用大模型引入正文初始化项目撰写脚本全局安装 成果展示 【AI】命令…

远程过程调用-buttonrpc源码解析5-函数绑定

前面几节的文章里提到过“通过一定的技术手段&#xff0c;通知远程服务器调用某个函数来执行相应的功能”&#xff0c;本片文章分析服务端如何使用std::bind函数&#xff0c;统一函数调用形式。 1、先看一个简单的例子&#xff1a; 温馨提示&#xff1a;std::bind除了绑定普通…

Linux——共享内存

Linux——共享内存 什么是共享内存共享内存原理Linux下共享内存的接口创建/获取共享内存&#xff1a;shmgetftok函数 映射共享内存到进程地址空间&#xff1a;shmat 解除共享内存映射&#xff1a;shmdt删除共享内存段&#xff1a;shmctl 利用共享内存进行通信 我们之前学习了匿…

关于未来自我的发展和一些学习方法(嵌入式方向)

我是一名大二的学生&#xff0c;考研还是就业&#xff0c;到底是重视专业课还是重视数学英语&#xff0c;这些问题一直困扰了我很久&#xff0c;但如今已经有了一些浅显的认识&#xff0c;所以才会想写这样一篇文章来记录一下自己的状态和未来的规划 下面的看法都是个人的看法&…

蓝桥杯刷题_day7_动态规划_路径问题

文章目录 DAY7下降路径最小和最小路径和地下城游戏 DAY7 下降路径最小和 【题目描述】 给你一个 n x n 的 方形 整数数组 matrix &#xff0c;请你找出并返回通过 matrix 的下降路径 的 最小和 。 下降路径 可以从第一行中的任何元素开始&#xff0c;并从每一行中选择一个元…

通过node 后端实现颜色窃贼 (取出某个图片的主体rgb颜色 )

1.需求 我前端轮播图的背景色 想通过每一张轮播图片的颜色作为背景色 这样的话 需要通过一张图片 取出图片的颜色 这个工作通过前端去处理 也可以通过后端去处理 前端我试了试 color-thief 的插件 但是 这个插件是基于canvas 的模式来的 我需要在小程序中使用这个插件 而且是…