引用一下习题的原文链接:https://blog.csdn.net/obession/article/details/68951351
大致问题就是:
小y有一个宽度为 100cm,高度为 20cm,深度为 1cm 的柜子,还有 36个礼物盒,他们的深度都为 1cm,有对应的宽度和高度。单位(cm)。
现在想把36件礼物盒子放到柜子上,由于礼物盒里面都装有礼物,礼物盒不堆放的放置。由于礼物盒深度和柜子深度一样,所以礼物盒和柜子深度方向也必须一致。并且礼物盒的高度不能大于柜子的高度,否者放不进去。小y希望放到柜子上礼物盒的宽度和正好等于柜子的宽度,也就是希望柜子两边都不存在间隙。在满足条件的情况下,小y 希望能尽可能多的放置礼物盒,算出最多能放多少个礼物盒。
开始解题:
收到问题当时第一反应写的代码思路 填入数据后删除不合规则的物品 代码如下
(不用这个方法,特别笨!!!! )

 // 更新物品listpublic static void updateList(List<Integer> listWide, List<Integer> listHigh, String[] text) {for (int i = 0; i < text.length; i++) {if (i % 2 == 0) // 偶数为宽{listWide.add(Integer.parseInt(text[i]));} else {listHigh.add(Integer.parseInt(text[i]));}}}// 记录物品高大于20的索引public static void recordIndex(List<Integer> list, List<Integer> number) {int num = 0;// 记录进行中的索引// 记录高大于20的索引for (Integer str : list) {if (str > 20) {number.add(num);}num++;}}// 删除高度>20对应索引的物品public static void removeList(List<Integer> list, List<Integer> number) {Iterator<Integer> iter = list.iterator();while (iter.hasNext()) {int item = iter.next();for (int i = 0; i < number.size(); i++) {if (item == number.indexOf(i)) {iter.remove();}}}}// 更新满足条件物品的宽高listpublic static void update(List<Integer> listWide, List<Integer> listHigh, List<Integer> number, String[] text) {updateList(listWide, listHigh, text);recordIndex(listHigh, number);removeList(listWide, number);removeList(listHigh, number);}public static void main(String[] args) {// 利用split直接将复制的元素装入text数组节省输入数据的时间 2i是宽 2i+1是高String[] text = "11 3 8 12 11 17 16 13 1 14 2 8 6 10 10 18 17 11 10 15 6 14 5 6 2 19 19 10 4 9 7 9 5 14 5 20 15 19 3 17 15 11 7 25 11 20 9 12 17 4 9 19 4 18 10 10 12 19 17 3 19 9 20 16 11 16 10 2 20 15 3 14".split(" ");// 筛选高度>20的排除 map集合更适合此操作 但为了保持有序(通过删除不合规则的高度确定删除宽度的索引)使用list 为优化时间复杂度 牺牲空间List<Integer> listWide = new ArrayList<>();// 创建宽的列表List<Integer> listHigh = new ArrayList<>();// 创建高的列表List<Integer> number = new ArrayList<>();// 创建高大于20的索引列表update(listWide, listHigh, number, text);// 删除不满足条件的物品更新物品列表// 排序// 计算}

优化上面逻辑问题
但是感觉思路好像有问题,一个排序题怎么弄的那么麻烦,后来突然想起来我不应该添加之后在筛选,应该筛选之后在添加,这样不仅能省去list删除不合规则的元素时记录索引和执行删除元素的时间,还能省去两个集合的内存和代码空间。于是将填入数据后删除不合规则的数据逻辑更改为只添加符合规则的数据,结合实际问题,我们只需要比较符合规则的物品宽度,于是2.0出现了。

// 更新物品listpublic static void updateList(List<Integer> listWide, String[] text) {for (int i = 0; i < text.length; i++) {if (i % 2 == 0) {// 加一个判断高大于20的方法,将满足的添加到物品集合if (Integer.parseInt(text[i + 1]) <= 20) {listWide.add(Integer.parseInt(text[i]));}}}}public static void main(String[] args) {// 利用split直接将复制的元素装入text数组节省输入数据的时间 2i是宽 2i+1是高String[] text = "11 3 8 12 11 17 16 13 1 14 2 8 6 10 10 18 17 11 10 15 6 14 5 6 2 19 19 10 4 9 7 9 5 14 5 20 15 19 3 17 15 11 7 25 11 20 9 12 17 4 9 19 4 18 10 10 12 19 17 3 19 9 20 16 11 16 10 2 20 15 3 14".split(" ");// 筛选高度>20的排除 map集合更适合此操作 但为了保持有序(通过删除不合规则的高度确定删除宽度的索引)使用list 为优化时间复杂度 牺牲空间List<Integer> listWide = new ArrayList<>();// 创建宽的列表updateList(listWide,text);//将满足物品的装入list// 排序 采用直接插入排序// 计算}

编写排序,考虑时间复杂度的问题原先准备快速排序,但由于数据太少用直接插入排序时间可能比快速排序所需时间更短。因为插入排序属于插入类型的排序,而快速排序属于交换类排序,数据量少时交换所消耗的资源占比大。于是便选择直接插入排序,当数据量大时在采用快速排序。又因为list集合不适合排序于是我们将list集合转为数组,调整逻辑。

 // list赋值给int数组public static int[] transform(List<Integer> listWide) {int[] wide = new int[listWide.size()];for (int i = 0; i < listWide.size(); i++) {wide[i] = listWide.get(i);}return wide;}// 直接插入排序public static void insertSort(int[] listWide) {int[] wide = Arrays.copyOf(listWide, listWide.length);// 从1开始遍历插入for (int i = 1; i < wide.length; i++) {int cup = wide[i]; // 记录要插入的数据int j = i;// 从排序后的序列最右侧开始比较,将小的放在左侧while (j > 0 && cup < wide[j - 1]) {wide[j] = wide[j - 1];j--;}// 索引不相等插入,相等停止插入if (j != i) {wide[j] = cup;}}count(wide);// 调用计算方法}

进行分两种情况,第一种最好情况现在宽度之和减去前面的一件刚好为100,例:现在1+2+2+3+4为10的删去2就行;第二种情况现在宽度减去前面2小件加上后面1大件刚好为100,例1+3+4+4+5后有7找和为15的,删去前面4,5加上后面7就行(理解成前面有两个数的和大于后面一个数的和,排序后和第一种情况一致)。

 // 计算public static void count(int[] listWide) {int sum = 0;for (int i = 0; i < listWide.length; i++) {if (sum < 100) {sum += listWide[i];} else {int index = i - 1;// 记录不满足时的索引int s = 0;for (int j = index - 1; j > 0; j--) {// 第一种可能 减去前面件数就为100 最好情况if (sum - listWide[j] <= 100) {s = sum - listWide[j];if (s == 100) {System.out.println("宽度和为" + s + "的礼物件数为:" + index + "件!");break;}}// 第二种 减去前面2件数加后面件数为100 最坏情况for (int k = index - 1; k < listWide.length; k++) {for (int l = index - 1; l > 0; l--) {if (s + listWide[k] - listWide[l] == 100) {System.out.println("宽度和为" + (s + listWide[k] - listWide[l])+ "的礼物件数为:" + index + "件!");break;}break;}}}break;}}

对代码进行测试,调用函数。

public static void main(String[] args) {// 利用split直接将复制的元素装入text数组节省输入数据的时间 2i是宽 2i+1是高String[] text = "11 3 8 12 11 17 16 13 1 14 2 8 6 10 10 18 17 11 10 15 6 14 5 6 2 19 19 10 4 9 7 9 5 14 5 20 15 19 3 17 15 11 7 25 11 20 9 12 17 4 9 19 4 18 10 10 12 19 17 3 19 9 20 16 11 16 10 2 20 15 3 14".split(" ");// 筛选高度>20的排除 map集合更适合此操作 但为了保持有序(通过删除不合规则的高度确定删除宽度的索引)使用listList<Integer> listWide = new ArrayList<>();// 创建宽的列表updateList(listWide, text);// 将满足物品的装入listinsertSort(transform(listWide));// 采用直接插入排序(数据量小直接插入排序快) transform()是将list赋值给int数组的方法(数组比集合方便排序)}


完整代码为代码块2-5,注意代码块2中的main方法更新为代码块5。

摸鱼日记
这道题是昨天晚上室友参加蓝桥杯比赛的辅导老师发的训练题目,本来窝当时买了瓶超大瓶的快乐水准备追番的,然后寝室讨论了这道题我也就参与进去了,由于平常上课时没有认真听课,可能导致实现方法有点低级,只能勉强解题,多多去掌握其他方法,加油,今天就先学到这,窝继续去摸鱼。
2021.11.22 晴

蓝桥杯训练-礼物盒问题-JAVA相关推荐

  1. 第十三届蓝桥杯模拟赛第二期JAVA组个人题解

    第十三届蓝桥杯模拟赛第二期JAVA组个人题解 文章目录 第十三届蓝桥杯模拟赛第二期JAVA组个人题解 题目1 题目2 题目3 题目4 题目5 题目6 题目7 题目8 题目9 题目10 题目1 小蓝的I ...

  2. 【算法练习】蓝桥杯训练一:区间k大数查询、最大最小公倍数、k好数

    蓝桥杯训练一 一.区间k大数查询(简单)(模拟) 二.最大最小公倍数(中等)(数论) 三.k好数(DP) 一.区间k大数查询(简单)(模拟) 直接模拟就可以,个人觉得题目不严谨,没有说重复元素,也没有 ...

  3. 2022年第十三届蓝桥杯大赛软件省赛Java学B组试题

    第十三届蓝桥杯大赛软件省赛Java学B组试题 一.试题截图 1. 星期计算 这道题是可以直接用笔算起来的,我算出来的答案是5,(2022整除7 余6,六天后就是星期五)但目前官方答案还不知道是什么? ...

  4. 蓝桥杯练习系统之基础训练Java版(2-26)—— 报时助手

    蓝桥杯练习系统之基础训练Java版(2-26)-- 报时助手 **难度等级:普通****关键字:字符串 条件判断** 问题描述: 给定当前的时间,请用英文的读法将它读出来.时间用时h和分m表示,在英文 ...

  5. 第十三届蓝桥杯大赛软件类决赛Java大学B组C题——左移右移

    [问题描述] 小蓝有一个长度为 N 的数组,初始时从左到右依次是 1, 2, 3, . . . N. 之后小蓝对这个数组进行了 M 次操作,每次操作可能是以下 2 种之一: 左移 x,即把 x 移动到 ...

  6. 第六届蓝桥杯大赛个人赛省赛Java B组真题

    文章目录 第六届蓝桥杯大赛个人赛省赛Java B组真题 1. 三角形面积(结果填空) 2. 立方自变身(结果填空) 3. 三羊献瑞(结果填空) 4. 循环节长度(代码填空) 5. 九数组分数(代码填空 ...

  7. 【蓝桥杯算法题】用java遍写税收计算

    [蓝桥杯算法题]用java遍写税收计算 题目:劳务报酬税收计算:输入 m ,输出税后收入.如果 m <=800,不扣税, 如果800< m <=4000.则 m 减去800后的金额扣 ...

  8. 蓝桥杯 基础练习 字母图形 JAVA

    蓝桥杯 基础练习 字母图形 JAVA 问题描述 利用字母可以组成一些美丽的图形,下面给出了一个例子: ABCDEFG BABCDEF CBABCDE DCBABCD EDCBABC 这是一个5行7列的 ...

  9. 第十届蓝桥杯大赛软件类决赛 Java大学C组

    蓝桥杯2019国赛Java大学C组题 试题 A: 奇数倍数 试题 B: 递增序列 试题 C: 平方拆分 试题 D: 切割 试题 E: 序列求和 试题 F: 最长子序列 试题 G: 数正方形 试题 H: ...

最新文章

  1. 排名看似毫无波澜的,但 R 语言热度仍在上升 | 8月编程语言排行
  2. 信令风暴问题根因分析
  3. FreeSwitch Sip【转】
  4. Mine Video Player – 视频播放器WordPress插件
  5. jquery 如何动态添加、删除class样式方法介绍_jquery_脚本之家
  6. python串口上位机画图_温度传感器+I2C+串口+PC上位机(pyserial)例子
  7. JavaScript 凭什么力压 Java、Python 横扫编程语言榜单?
  8. linux shell基础(1)
  9. C++字符串使用sizeof时注意
  10. i3wm 获取window class
  11. 搜狗linux 如何启动程序,完美解决搜狗输入法"请启用fcitx-qimpanel面板程序"的方法...
  12. PHP 获取微视无水印源地址_最新抖音短视频无水印地址解析原理(抖音免费解析接口),以PHP代码为例...
  13. 太平洋服务器cpu型号,Intel正式发布:新一代6W的超低功耗平台CPU
  14. 二级域名 免费+免备案
  15. 2019年外卖市场分析:本地外卖创业要注意哪些趋势?
  16. HDU 5745 La Vie en rose(DP+bitset优化)
  17. iOS 更改webView文字颜色丶文字大小丶背景色的方法
  18. linux可以打开浏览器嘛,Linux下怎样可以打开浏览器?
  19. 如何系统地学习 C++ 语言?
  20. 正则判断只能输入大于0的正整数

热门文章

  1. Redis-Linux中安装Redis、命令操作Redis
  2. 苹果手机测距离_iphone 12 pro测身高怎么玩? iPhone12 pro测身高玩法教程分享[多图]-软件教程...
  3. python-opencv学习笔记2 核心运算
  4. crt查看开机日志_securecrt查看日志
  5. 鹏博士100万“贱卖”长城宽带:摆脱巨亏“拖油瓶”,寻求轻资产转型
  6. java实现方差分析(ANOVA)
  7. Java String 截取至小数点后两位
  8. CAD的秘密小技巧——关联性阵列
  9. MortIIs Story
  10. python-回文数判断