ybt1226 装箱问题

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\n", ans);//输出答案
		for (int i = 1; i <= 6; i++) {//进行下一轮输入
			scanf("%d", &a[i]);
			if (a[i]) {
				flag = 1;
			}
		}
	}
	return 0;
}
posted @ 2020-02-20 17:17  Wild_Donkey  阅读(324)  评论(0编辑  收藏  举报