算法作业 (三)——— 装箱问题

  这周的问题终于有些难度了,终于不是一眼看过去就有能写出大概的题目了,还有就是,我又找不到题目了,所以去网上扒了一下,英语的:

Packets
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 28329   Accepted: 9291

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 


看完题我第一反应就是贪心,用最少的箱子装最多的货物。确定了贪心之后便开始思考,如何解题。首先每一新箱子都有 6*6 = 36 的空间,然后看货物,细细一想,发现 边长大于3的货物都需要单独开一个箱子,所以便有了第一行代码
sum += goods4 + goods5 + goods6;

  又反复的思考了一下3的情况 一个 6*6的箱子能够装4个3*3的箱子。所以上面的算法就可以修改成

 sum += goods4 + goods5 + goods6 + ((goods3 - 1) / 4 + 1);//向上取整,多出来的一个必须多开一个箱子

  为什么多出来的3*3货物必须多开一个箱子呢,分析一下空间就可以了,题目中说物品高度相同,所以只需要考虑占地面积,5*5 和 4*4 的货物所占的盒子虽然还有空间,但是它们余下的空间只能够存放1*1或者2*2的货物,所以多出来的3*3必须额外开辟一个空间。到了这一步问题就来了,3*3的货物是4的倍数那最好,如果3*3的货物不是4的倍数,那么就必须额外开一个箱子,用来存放余下的3*3的货物,那么存放多余的的组成不成一件3*3的货物肯定会有多余空间,而且余数不止一种,我们就需要进行分类讨论。嗯好,我们来继续分析,现在3*3的货物是被全部放下了,但是由于3*3的货物不是 4 的倍数, 难么肯定就会有多余的空间,而且根据余数的不同肯定有不同的情况。那么余数有几种可能呢 ?唔,让我们来想一想,一个 箱子可以放4个3*3,那么x%4的可能只有4种吧,0、1、2、3 。

  现在我们来分析一下 3*3 的情况,无剩余的情况就不分析了

    画个图就可以直观的看到结果了:

      由图可知:

    1、当余下1个的时候还能装7个1*1和5个2*2, 

    2、当余下2个的时候还能装6个1*1和3个2*2,

    2、当余下3个的时候还能装5个1*1和1个2*2,

  得出相应的代码:

if (goods3 % 4 == 1)
        {
            spaceby1 += 7;
            spaceby2 += 5;
        } //余下1个3*3所余下的1*1和2*2的空间
        if (goods3 % 4 == 2)
        {
            spaceby1 += 6;
            spaceby2 += 3;
        } //余下2个3*3所余下的1*1和2*2的空间
        if (goods3 % 4 == 3)
        {
            spaceby1 += 5;
            spaceby2 += 1;
        } //余下3个3*3所余下的1*1和2*2的空间

处理完3*3的就简单了,我们按顺序去处理2*2的货物. 在这之前们需要求出有多少地方可以存储2*2的货物,5*5是无法存储2*2 的货物的,但是4*4的可以4*4的里面还可以存放5个2*2 所以我们需要加上goods2

4*5。好了2*2的空间算完,那还得分类论。

  很显然分为3总情况:

    1、刚好存下,皆大欢喜

    2、存不下,还得开空间

    3、有剩余,计算剩余空间

  让2*2的空间数与货物数进行比较够的话,就不用额外开空间了不够的话直接开空间

  代码如下:

  

        spaceby2 += 5 * goods4; //装一个4*4的时候余下的1*1和2*2的空间

        if (spaceby2 < goods2) //2*2的空间小于2*2的盒子
        {
            //额外的2*2空间需要的箱子
            sum += ((goods2 - spaceby2 - 1) / 9 + 1);
        }

  余下1*1 的模仿2*2的流程即可,1*1剩余空间建议用总箱子数*36 - 被占用的空间这样就可以快速的得出1*1的空间而且不容易错,(2*2不用这个方法是因为5*5的碎片空间虽然足够但是呢,它边长就……6*6,放不下2*2)1*1的就不单独贴代码了

  下面贴一下完整的代码(能自己写出来的先自己写一遍):

  

#include <stdio.h>

int main()
{
    int goods1, goods2, goods3, goods4, goods5, goods6; //1,2,3,4,5,6
    while (scanf("%d %d %d %d %d %d", &goods1, &goods2, &goods3, &goods4, &goods5, &goods6) != EOF)
    {
        int sum = 0, spaceby1 = 0, spaceby2 = 0; //sum总箱子数,n余下放1x1的位置,m余下放2x2的位置
        if (goods1 == 0 && goods2 == 0 && goods3 == 0 && goods4 == 0 && goods5 == 0 && goods6 == 0)
        {
            return 0;
        }
        sum += goods4 + goods5 + goods6 + ((goods3 - 1) / 4 + 1); //最少需要开的箱子
        if (goods3 % 4 == 1)
        {
            spaceby1 += 7;
            spaceby2 += 5;
        } //余下1个3*3所余下的1*1和2*2的空间
        if (goods3 % 4 == 2)
        {
            spaceby1 += 6;
            spaceby2 += 3;
        } //余下2个3*3所余下的1*1和2*2的空间
        if (goods3 % 4 == 3)
        {
            spaceby1 += 5;
            spaceby2 += 1;
        }           //余下3个3*3所余下的1*1和2*2的空间
        spaceby2 += 5 * goods4; //装一个4*4的时候余下的1*1和2*2的空间

        if (spaceby2 < goods2) //2*2的空间小于2*2的盒子
        {
            //额外的2*2空间需要的箱子
            sum += ((goods2 - spaceby2 - 1) / 9 + 1);
        }
        //余下了多少 1*1 的空间
        spaceby1 = 36 * sum - 36 * goods6 - 25 * goods5 - 16 * goods4 - 9 * goods3 - 4 * goods2;

        if (spaceby1 < goods1)
        {
            sum += ((goods1 - spaceby1 - 1) / 36 - 1);
        }
        printf("%d\n", sum);
    }
    return 0;
}
代码

猜你喜欢

转载自www.cnblogs.com/daker-code/p/11456717.html