ybt1226 装箱问题
【题目描述】
一个工厂制造的产品形状都是长方体,它们的高度都是h,长和宽都相等,一共有六个型号,他们的长宽分别为1×1,2×2,3×3,4×4,5×5,6×6。这些产品通常使用一个6×6×h的长方体包裹包装然后邮寄给客户。因为邮费很贵,所以工厂要想方设法的减小每个订单运送时的包裹数量。他们很需要有一个好的程序帮他们解决这个问题从而节省费用。现在这个程序由你来设计。
【输入】
输入文件包括几行,每一行代表一个订单。每个订单里的一行包括六个整数,中间用空格隔开,分别为1×1至6×6这六种产品的数量。输入文件将以6个0组成的一行结尾。
【输出】
除了输入的最后一行6个0以外,输入文件里每一行对应着输出文件的一行,每一行输出一个整数代表对应的订单所需的最小包裹数。
【输入样例】
0 0 4 0 0 1
7 5 1 0 0 0
0 0 0 0 0 0
【输出样例】
2
1
【题解】
和乌鸦喝水放石头一个道理,先放大的,再放小的.
从大到小分析,6*6的箱子直接占满,所以ans+=a[6],不留空隙
5*5的箱子只能放一个,ans+=a[5]空隙只能放最小的箱子11个.
4*4的箱子也是只放一个,ans+=a[4],空隙可以放第二小的箱子5个,如果第二小的箱子放完了,就把剩下的空隙放最小的箱子.
3*3的箱子可以放四个.如果最后有结余,那么就视情况放第二小的箱子最小的箱子(第2小的优先).
根据3*3箱子的数量分类讨论,情况可以分为:
1个3*3,最多放5个第二小的箱子,剩下的空隙放最小的.
2个3*3,最多放3个.
3个3*3,最多1个.
找出规律:最后空隙可以塞下的2*2箱子数量为:2(3-a[3]%4)-1
最后,如果2*2的箱子还有结余,那么ans+=a[2]/9(能放9个)
如果不能整除,就再加一个容器装最后的余数,剩余空隙用1*1箱子补齐.
最后的1*1的箱子如果还没放完,直接满满地放,放完为止.
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int a[7], ans = 0, t;
bool flag = 0;
int main() {
for (int i = 1; i <= 6; i++) {
scanf("%d", &a[i]);
if (a[i]) {
flag = 1;//只要非0,就打标记
}
}
while (flag) {//只要有一个数不为零,就继续执行
flag = 0;//清空标记
ans = 0;//答案归零
ans += a[6];//6*6的箱子直接放满
if (a[5] > 0) {//5*5的箱子
a[1] -= 11 * a[5];//只能放得开1*1的箱子
ans += a[5];
}
if (a[4] > 0) {
ans += a[4];
t = a[2] - (a[4] * 5);
if (t <= 0) {//2*2的箱子全部放完
a[1] -= (a[4] * 20) - a[2] * 4;//剩余空隙放1*1
a[2] = 0;
}
else {//空隙填满2*2的箱子
a[2] -= a[4] * 5;
}
}
if (a[3] > 0) {//处理3*3的格子
ans += a[3] / 4;
a[3] %= 4;//4个3*3不留空隙
if (a[3]) {
ans++;
t = (4 - a[3]) * 2 - 1;//这就是前面分析的当已经放a[3]个3*3的箱子时,空隙最多能放的2*2的箱子数量.
if (a[2] > t) {//放满2*2
a[2] -= t;//最大限度放2*2
a[1] -= 36 - 9 * a[3] - t * 4;//空隙填满1*1
}
else {//空隙放完2*2的箱子
a[2] = 0;
a[1] -= 36 - 9 * a[3] - a[2] * 4;//剩余空隙放1*1的
}
}
}
if (a[2] > 0) {//到这里还有2*2的箱子
ans += a[2] / 9;
if (a[2] % 9) {
ans++;
a[1] -= 36 - ((a[2] % 9) * 4);
}
}
if (a[1] > 0) {//到这里还有1*1的箱子
ans += a[1] / 36;//
if (a[1] % 36) {
ans++;
}
}
printf("%d
", ans);//输出答案
for (int i = 1; i <= 6; i++) {//进行下一轮输入
scanf("%d", &a[i]);
if (a[i]) {
flag = 1;
}
}
}
return 0;
}