Description
Input
Output
Sample Input
0 0 4 0 0 1 7 5 1 0 0 0 0 0 0 0 0 0
Sample Output
2 1
装箱问题
一个工厂制造的产品形状都是长方体,它们的高度都是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:1个产品放在1个箱子里
5*5:1个产品要占用1个箱子,用1*1的箱子可以填充(11个填满1箱)
4*4:1个产品要占用1个箱子,剩余空间用2*2和1*1的箱子填充(先填充2*2,再填充1*1)
3*3:4个产品可以填满1个箱子,假如有不满1个箱子的,分情况用1*1和2*2的产品填满
2*2:9个产品可以填满1个箱子,假如有不满1个箱子的,用1*1的产品填充
1*1:36个产品可填满一个箱子
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int[] a = new int[6];
while(true){
boolean isExit = true;
for(int i=0; i<a.length; i++){
a[i] = sc.nextInt();
if(a[i] != 0){
isExit = false;
}
}
if(isExit){
break;
}
int count = 0;
//6*6有多少个,就要用多少包裹
count += a[5];
//5*5的有多少,就要用多少个包裹,但是多余的空间可以放1*1
for(int i=0; i<a[4]; i++){
count++; //用一个包裹
a[0] -= 11; //再放11个1*1的包裹
}
if(a[0]<0){
//说明1*1的包裹放完了,设置其值为0
a[0] = 0;
}
//4*4的有多少,就要用多少个包裹
for(int i=0; i<a[3]; i++){
count++;//用一个包裹
if(a[1]>=5){
//如果2*2的包裹大于或者等与5个,就直接放2*2的包裹
a[1] -= 5;
}else if(a[1]>0){
//如果2*2的包裹 大于0,小于5,那么多余的空间放1*1的包裹
//多余的空间是36-16-4*a[1] = 20-4*a[1]
a[0] -= 20-4*a[1];
a[1] -= a[1];
}else{
//全放1*1的包裹,可以放36-16 = 20个
a[0] -= 20;
}
}
if(a[0] < 0){
//说明1*1的包裹放完了,设置其值为0
a[0]=0;
}
//3*3的包裹要分4中情况
//首先4的倍数部分要用的包裹数,先计算,计算规则是每4个用1个包裹
count += a[2]/4;
//取模看多几个3*3的箱子
int x = a[2]%4;
switch (x) {
case 0:
//什么都不管
break;
case 1:
//占用1个包裹,多余的空间可以放5个2*2,并且放7个1*1
count++;
if(a[1]>=5){
//如果2*2的包裹大于或者等与5个,就直接放2*2的包裹
a[1] -= 5;
a[0] -= 7;
}else if(a[1]>0){
//如果2*2的包裹 大于0,小于5,那么多余的空间放1*1的包裹
//多余的空间是36-9-4*a[1] = 27-4*a[1]
a[0] -= 27-4*a[1];
a[1] -= a[1];
}else{
//全放1*1的包裹,可以放36-9 = 27个
a[0] -= 27;
}
break;
case 2:
//占用1个包裹,多余的空间可以放3个2*2,并且放6个1*1
count++;
if(a[1]>=3){
//如果2*2的包裹大于或者等与5个,就直接放2*2的包裹
a[1] -= 3;
a[0] -= 6;
}else if(a[1]>0){
//如果2*2的包裹 大于0,小于5,那么多余的空间放1*1的包裹
//多余的空间是36-18-4*a[1] = 18-4*a[1]
a[0] -= 18-4*a[1];
a[1] -= a[1];
}else{
//全放1*1的包裹,可以放36-18 = 18个
a[0] -= 18;
}
break;
case 3:
//如果有3个箱子,占用1个包裹,多余的空间可以放1个2*2,并且放5个1*1
count++;
if(a[1]>0){
//放一个2*2,放5个1*1
a[1] -= 1;
a[0] -= 5;
}else{
//全放1*1,可以放9个
a[0] -= 9;
}
break;
default:
break;
}
if(a[0] < 0){
a[0] = 0;
}
//最后来做2*2的,全放的话,可以放9个
count += a[1]/9;
int y = a[1]%9;
if(y>0){
//说明确实有2*2的箱子多
count++;
//剩余空间装1*1
a[0] -= 36-4*y;
a[1] = 0;
}
if(a[0]<0){
a[0]=0;
}
//最后来做1*1的,全放的话,可以放36个
count += a[0]/36;
int z = a[0]%36;
if(z>0){
count++;
a[0] = 0;
}
System.out.println(count);
}
}
}