poj日记(1017)——贪心算法

来源:互联网 发布:js中集合和数组的区别 编辑:程序博客网 时间:2024/06/06 09:56

Description

A factory produces products packed in square packets of the same height h and of the sizes 1*1, 2*2, 3*3, 4*4, 5*5, 6*6. These products are always delivered to customers in the square parcels of the same height h as the products have and of the size 6*6. Because of the expenses it is the interest of the factory as well as of the customer to minimize the number of parcels necessary to deliver the ordered products from the factory to the customer. A good program solving the problem of finding the minimal number of parcels necessary to deliver the given products according to an order would save a lot of money. You are asked to make such a program.

Input

The input file consists of several lines specifying orders. Each line specifies one order. Orders are described by six integers separated by one space representing successively the number of packets of individual size from the smallest size 1*1 to the biggest size 6*6. The end of the input file is indicated by the line containing six zeros.

Output

The output file contains one line for each line in the input file. This line contains the minimal number of parcels into which the order from the corresponding line of the input file can be packed. There is no line in the output file corresponding to the last ``null'' line of the input file.

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);          }      }  } 



原创粉丝点击