Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 46658 | Accepted: 15782 |
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
21
import java.util.Scanner; /** * * 装箱问题 问题描述 一个工厂制造的产品形状都是长方体,它们的高度都是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 解题思路 这个问题描述得比较清楚,我们在这里只解释一下输入输出样例:共有两组有效输入, 第一组表示有4 个3*3 的产品和一个6*6 的产品,此时4 个3*3 的产品占用一个箱子,另外 一个6*6 的产品占用1 个箱子,所以箱子数是2;第二组表示有7 个1*1 的产品,5 个2*2 的产品和1 个3*3 的产品,我们可以把他们统统放在一个箱子中,所以输出是1。 分析六个型号的产品占用箱子的具体情况如下:6*6 的产品每个会占用一个完整的箱 子,并且没有空余空间;5*5 的产品每个占用一个新的箱子,并且留下11 个可以盛放1*1 的产品的空余空间;4*4 的产品每个占用一个新的箱子,并且留下5 个可以盛放2*2 的产品 的空余空间;3*3 的产品情况比较复杂,首先3*3 的产品不能放在原来盛有5*5 或者4*4 的 箱子中,那么必须为3*3 的产品另开新的箱子,新开的箱子数目等于3*3 的产品的数目除以 4 向上取整;同时我们需要讨论为3*3 的产品新开箱子时,剩余的空间可以盛放多少2*2 和 1*1 的产品(这里如果有空间可以盛放2*2 的产品,我们就将它计入2*2 的空余空间,等到 2*2 的产品全部装完,如果还有2*2 的空间剩余,再将它们转换成1*1 的剩余空间)。我们 可以分情况讨论为3*3 的产品打开的新箱子中剩余的空位,共为四种情况:第一种,3*3 的 产品的数目正好是4 的倍数,所以没有空余空间;第二种,3*3 的产品数目是4 的倍数加1, 这时还剩5 个2*2 的空位和7 个1*1 的空位;第三种,3*3 的产品数目是4 的倍数加2,这 时还剩3 个2*2 的空位和6 个1*1 的空位;第四种,3*3 的产品数目是4 的倍数加3,这时 还剩1 个2*2 的空位和5 个1*1 的空位;处理完3*3 的产品,就可以比较一下剩余的2*2 的空位和2*2 产品的数目,如果产品数目多,就将2*2 的空位全部填满,再为2*2 的产品打 开新箱子,同时计算新箱子中1*1 的空位,如果剩余空位多,就将2*2 的产品全部填入2*2 的空位,再将剩余的2*2 的空位转换成1*1 的空位;最后处理1*1 的产品,比较一下1*1 的空位与1*1 的产品数目,如果空位多,将1*1 的产品全部填入空位,否则,先将1*1 的空 位填满,然后再为1*1 的产品打开新的箱子。 * */ 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; } //如果6*6的有几个,每个需要占用1个包裹,没有多余空间; //如果5*5的有几个,每个要占用1个包裹,多出来的可以放11个1*1; //如果4*4的有几个,每个要占用1个包裹,多出来的可以放5个2*2,或者放20个1*1; //如果3*3的有几个,情况就很复杂: //(1)3*3的有1个,占用1个包裹,多余的空间可以放5个2*2,并且放7个1*1; //(2)3*3的有2个,占用1个包裹,多余的空间可以放3个2*2,并且放6个1*1; //(3)3*3的有3个,占用1个包裹,多余的空间可以放1个2*2,并且放5个1*1; //(4)3*3的有4个,占用1个包裹,没多余空间 //最少需要的包裹数量 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); } } }