【题目链接】

ybt 1226:装箱问题
OpenJudge NOI 4.6 19:装箱问题

【题目考点】

1. 贪心

【解题思路】

该题说是三维立方体,实际上无论是包裹还是产品,高度都是h,因而不用考虑高度,这实际上是二维平面上的问题。

1. 贪心选择性质的证明

贪心选择:选择最大的可以装入该包裹的产品装入该包裹

  1. 证明:存在最优解包含第一次的贪心选择。即存在最优解,第一个包裹中包含最大产品。

假设所有最优解都不包含第一次的贪心选择,即第一个包裹C中不包含最大的产品x。
最大的产品x一定存在于某个包裹内,记那个包裹为N。我们可以将N中的所有产品和C中的所有产品完全交换。总包裹数量不变,第一个包裹C中存在产品x,这与假设相悖,假设不成立,原命题得证。

  1. 证明:前k步都做贪心选择,存在最优解包含第k+1步的贪心选择。

是否做贪心选择区别在于:当前拿到一个最大的可以装入当前包裹C的产品x,是将这个产品放在当前包裹C中,还是将其放在一个新包裹N中。贪心选择是将其放在当前包裹C中。
使用反证法:假设对所有最优解,在装第k+1个产品时,当前关注的包裹C可以装入的最大产品为x,此时不进行贪心选择,不选择x,接下来只会装入大小小于x的产品。也可以说,当前包裹C中,产品x的数量不会更多。
下面考虑在N中包括x的部分产品能否和C中的一些产品或空位交换,且两包裹仍能装得下。如果可以,那么说明第k+1步进行了贪心选择,选择了产品x,总包裹数量不变,也是最优解。假设不成立,原命题得证。

  • 如果N中x的数量大于C中x的数量,且x在C中与N中都是最大的产品,那么可以将N与C中的所有产品整体交换。
    x为4*4、5*5、6*6都满足这一情况。或C中3*3的个数比N中3*3的个数更少。
    例:x为5*5,在第k+1步往C中装产品时,没有按照贪心选择将5*5的产品装入C。后来5*5的产品装入了N,C中又装了一些产品。将C与N的所有产品交换后,C中存在贪心选择,总包裹数仍然最少,说明存在最优解在第k+1步进行了贪心选择,假设不成立,原命题得证。

    以下为N中x的数量小于等于C中x的数量的情况:
  • 如果x是1*1的产品,那么C当时可以放1*1的产品但不放,存在一些位置空着,C中一定有可以放下1*1的空位。可以完成交换。
  • 如果x是2*2的产品,那么C当时可以放2*2的产品但不放,去放1*1的产品或空着。那么在C中一定可以选择出2*2的区域,其中可以是1*1的产品也可以是空位,与x进行交换。
  • 如果x是3*3的产品,说明先前加入C的是若干个3*3的产品。
  1. 如果C中已经有3个3*3的产品,剩下3*3的位置,这部分位置的产品或空位都可以与x进行交换。
  2. 如果C中已经有2个3*3的产品,且剩余的空间中摆了至多3个2*2的产品。
    N中有2个3*3产品与至多3个2*2产品,此时,把N中的1个3*3与C中的2个2*2与1个1*1交换,结果为C中有3个3*3与1个2*2,N中有1个3*3与5个2*2,这种交换是可行的。
    同理,如果N中有1个3*3与至多5个2*2,用N中的1个3*3交换C中的2个2*2与1个1*1是可行的。
    例:将N中的红色3*3产品x与C中的蓝色两个2*2产品与1个1*1产品进行交换。交换 后一些1*1产品位置发生变化。
  3. 如果C中已经有1个3*3产品,剩余空间摆了至多5个2*2的产品。N中有1个3*3产品与至多5个2*2的产品,用N中的1个3*3交换C中的2个2*2与1个1*1是可行的。
    如果待交换的产品没有那么多,可以用空位代替。
    例:将N中的红色3*3产品x与C中的蓝色两个2*2产品与1个1*1产品进行交换。交换 后一些1*1产品位置发生变化。
  • x不可能是4*4或更大的产品,如果是,C中可以放x但不放,C中的x只能是0个,而N中的x有1个,这是前面已经讨论过的“如果N中x的数量大于C中x的数量”的情况。
    因此N中包括x的部分产品总能和C中的一些产品或空位交换位置。说明第k+1步进行了贪心选择,选择了产品x,总包裹数量不变,也是最优解。因而假设不成立,原命题得证。

2. 具体做法

考虑各种情况下,剩下的空间最多可以放下几个各种产品,总结成表格

已有 最多放几个3*3 最多放几个2*2 最多放几个1*1
1个6*6 0 0 0
1个5*5 0 0 11
1个4*4 0 5 20
1个3*3 3 5 27
2个3*3 2 3 18
3个3*3 1 1 9
4 9 36

此这基础上,每多放一个2*2,1*1可放个数减4。
观察规律,1*1可以放的个数就是总面积6*6减去所有放入其中的产品的总面积。
在已有3*3的情况下,每多放入一个3*3,2*2可以放入的个数减2。
这里只需要设数组记录放入1个某大小产品后,其他大小产品可以放入的数量。

从大到小遍历各个产品,找到一个产品,开一个新包裹将其放入。如果剩余位置还可以放产品,那么放入对应产品,改变剩余位置可放产品的数量。直到没有位置可放或没有足够的产品可放为止。再从大到小找下一个产品,开一个新包裹将其放入。重复上述过程,直到看完所有产品为止。

【题解代码】

解法1:贪心(本人原创)

#include <bits/stdc++.h>
using namespace std;
int status[8][4];//status[i][j]:包裹中已有1个大小为i*i的产品,此时可以最多放入多少个j*j的产品
void initStatus()
{//status[0]:包裹中没有产品时,各种产品最多可以放多少个 status[2][2] = 8;status[3][2] = 5, status[3][3] = 3;status[4][2] = 5;for(int i = 1; i <= 6; ++i)status[i][1] = 36 - i*i;
}
int pro[8];//pro[i]:i*i产品的数量
int main()
{initStatus(); while(true){int sum = 0, bag = 0, rem[8];//sum:总产品数量  bag:包裹数 rem[i]:当前剩余空间能放几个i*i for(int i = 1; i <= 6; ++i){cin >> pro[i];sum += pro[i];}if(sum == 0)//如果6个数都是0,那么加和为0,要跳出循环 break;for(int i = 6; i >= 1; --i){while(pro[i] > 0){bag++;//用一个新包裹放i*ipro[i]--;for(int j = 1; j <= 3; ++j)//获取当前剩余空间情况 rem[j] = status[i][j];int j = 3;while(j >= 1){if(rem[j] > 0 && pro[j] > 0)//如果可以放j*j的产品 {pro[j]--;//放一个产品 if(j == 3){rem[3]--;rem[2] -= 2;rem[1] -= 9;}else if(j == 2){rem[2]--;rem[1] -= 4;}else//j == 1rem[1]--;}else--j;}}   }cout << bag << endl;}  return 0;
}

解法2:手动完成贪心过程

思路来自zqhf123博客:zqhf123 1226:装箱问题
由于箱子种类不多,我们可以手动完成每一步的贪心行为。先装大产品,看占了多少空间,剩下多少空间。再看小产品。逐次算出当前可以给下一个产品留出的空位。

#include<bits/stdc++.h>
using namespace std;
int bag;//总包裹数
int k[4] = {0, 5, 3, 1};//k[i]表示3*3的产品有i个时(k[0]表示有4个时)剩余空间可以放2*2产品的个数
int pro[8], p2, p1;//p2:2*2空位数 p1:1*1空位数
int main()
{ while(true){for(int i = 1; i <= 6; ++i)cin >> pro[i];if(pro[1] == 0 && pro[2] == 0 && pro[3] == 0 && pro[4] == 0 && pro[5] == 0 && pro[6] == 0) break;bag = pro[6] + pro[5] + pro[4] + ceil(pro[3]/4.0);//6*6和5*5和4*4一定是一个占一个箱子,而3*3 4个占一个箱子p2 = 5*pro[4]+k[pro[3]%4];//k[pro[3]%4]:有pro[3]%4个3*3在一个包裹中时,剩下的位置可以放2*2的数目  if(pro[2] > p2)//2*2的个数比我们留出来为2*2的空间个数多,就需要为2*2另开箱子bag += ceil((pro[2]-p2)/9.0);//多出来的2*2箱子应该占用的新箱子数 p1 = 36*bag-36*pro[6]-25*pro[5]-16*pro[4]-9*pro[3]-4*pro[2];//求出当前包裹中所有剩下的可以放1*1的位置数 if(pro[1] > p1)//如果1*1的个数,比我们留出的空间多就需要另开空间 bag += ceil((pro[1]-p1)/36.0);//将多出来的另开箱子 cout << bag << endl;}return 0;
}

信息学奥赛一本通 1226:装箱问题 | OpenJudge NOI 4.6 19:装箱问题相关推荐

  1. 信息学奥赛一本通(2049:【例5.19】字符串判等)

    2049:[例5.19]字符串判等 时间限制: 1000 ms         内存限制: 65536 KB 提交数: 842     通过数: 254 [题目描述] 判断两个由大小写字母和空格组成的 ...

  2. 信息学奥赛一本通(2033:【例4.19】阶乘之和)

    2033:[例4.19]阶乘之和 时间限制: 1000 ms         内存限制: 65536 KB 提交数: 1896     通过数: 313 [题目描述] 输入nn,计算S=1!+2!+3 ...

  3. 信息学奥赛一本通 1209:分数求和 | OpenJudge NOI 1.13 12:分数求和

    [题目链接] ybt 1209:分数求和 OpenJudge NOI 1.13 12:分数求和 [题目考点] 1. 求最大公约数 2. 求最小公倍数 [解题思路] 求最大公约数,可以用辗转相除法.具体 ...

  4. 信息学奥赛一本通 1294:Charm Bracelet | OpenJudge NOI 2.6 7113:Charm Bracelet | 洛谷 P2871

    [题目链接] ybt 1294:Charm Bracelet OpenJudge NOI 2.6 7113:Charm Bracelet 洛谷 P2871 [USACO07DEC]Charm Brac ...

  5. 信息学奥赛一本通 2050:【例5.20】字串包含 | OpenJudge NOI 1.17 19:字符串移位包含问题

    [题目链接] ybt 2050:[例5.20]字串包含 OpenJudge NOI 1.17 19:字符串移位包含问题 [题目考点] 1. 字符串 2. 判断一个字符串是不是另一个字符串的子串(字符串 ...

  6. 信息学奥赛一本通 1073:救援 | OpenJudge NOI 1.5 19:救援

    [题目链接] ybt 1073:救援 OpenJudge NOI 1.5 19:救援 [题目考点] 1. 直角坐标系下某点到原点的距离 点(x,y)(x,y)(x,y)到原点的距离d=x2+y2d = ...

  7. 信息学奥赛一本通 1057:简单计算器 | OpenJudge NOI 1.4 19

    [题目链接] ybt 1057:简单计算器 OpenJudge NOI 1.4 19:简单计算器 [题目考点] 1. switch语句 2. if-else if-else语句 [题解代码] 解法1: ...

  8. 信息学奥赛一本通 1036:A×B问题 | OpenJudge NOI 1.3 19

    [题目链接] ybt 1036:A×B问题 OpenJudge NOI 1.3 19:A*B问题 [题目考点] 1. 不同整型数据的范围 类型 占用字节数 可表示数字范围 char 1 -127~12 ...

  9. 信息学奥赛一本通(基础算法与数据结构-题解汇总目录)

    信息学奥赛一本通(C++版)在线评测系统 基础(二)基础算法   更新中...... 第一章高精度计算 1307[例1.3]高精度乘法 1308[例1.5]高精除 1309[例1.6]回文数(Noip ...

最新文章

  1. 似水流年,美丽清华园
  2. @Configuration
  3. 塔菲尔曲线斜率的大小_分段函数函数值(自变量)大小(范围)的六种题型
  4. 附录:MySQL忘记root密码
  5. Greg and Array CodeForces - 296C(差分数组+线段树)
  6. 谷歌开源的 GAN 库--TFGAN
  7. ccf json解析 java,【求助】e4a json解析 求助大佬帮忙老看下怎么取?
  8. Python最实用的25个小技巧
  9. python selenium list index out of range
  10. 做开源 18 年,他想把中国开源带向世界 | 人物志
  11. “中国互联网100强”(2013)发布
  12. bootstrap 获取表格修改的结果_bootstrap table getData获取表格数据的方法
  13. Linu下安装ffmpeg
  14. MAC - 必备软件安装与使用
  15. 黑马Python笔记3
  16. 照片宽高比怎么设置_【经验分享】照片处理
  17. IntelliJ IDEA 激活 破解补丁
  18. 抑郁焦虑测试软件可信度,做题自测抑郁症可靠吗
  19. Cross Domian iFrame Exceptions 跨域iFrame屏蔽例外
  20. 初学画画怎么画线稿?学画线稿的方法有哪些?

热门文章

  1. lucene 多索引目录搜索实现方法
  2. [转载]Windowsnbsp;Servernbsp;2008nbsp;R2nbsp;之二十五ADnbsp;RMS信任策略
  3. webservice 心得
  4. 进程函数一步步理解Linux进程(2)--进程编程进程函数
  5. ios公司开发者账号申请分享攻略
  6. 刚刚!阿里云宣布2021要“做厚中台”!有哪些书值得读?
  7. 深入线程池的问题连环炮
  8. 阿里高级技术专家张建飞:深度剖析领域模型vs数据模型的用法
  9. ElementUI + express实现头像上传及后台图片保存
  10. 分布式开发必须了解的Zookeeper的Leader选举机制(源码解析)