算法作業 (三)——— 裝箱問題


  這周的問題終於有些難度了,終於不是一眼看過去就有能寫出大概的題目了,還有就是,我又找不到題目了,所以去網上扒了一下,英語的:

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>
/**
 * @author 楊文蓁的小迷弟
 * @note   算法作業3
 * @date   2019/09/05
 */
int main()
{
    //北大OJ數據超過了正常的int,估計有一個50000的數據
    unsigned 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)
    {
        unsigned 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 +3) / 4); //最少需要開的箱子
        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 + 8) / 9);
        }
        //余下了多少 1*1 的空間
        spaceby1 = 36 * sum - 36*goods6 - 25*goods5 - 16*goods4 - 9*goods3 - 4*goods2;

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

 

 貼個python的代碼:

#author: 楊文蓁的小迷弟
#date:   2019/9/5

while (1):
    s=input().split()
    box_sum = spaceby1 = spaceby2 = 0
    flag = True
    for i in range(len(s)):
        if int(s[i]) != 0:
            flag = False
    if flag == True:
        exit()

    box_sum = int(s[5]) + int(s[4]) + int(s[3]) + (int(s[2])-1) // 4+1

    if int(s[2])%4 == 1:
        spaceby1 += 5
        spaceby2 += 7

    if int(s[2])%4 == 2:
        spaceby1 += 6
        spaceby2 += 3

    if int(s[2])%4 == 3:
        spaceby1 += 5
        spaceby2 += 1

    spaceby2 += 5 * int(s[3])

    if spaceby2 <= int(s[1]):
        box_sum += ((int(s[1])-spaceby2-1)//9 + 1)
    
    spaceby1 = 36*box_sum - 36*int(s[5]) - 25*int(s[4]) - 16*int(s[3]) - 9*int(s[2]) - 4*int(s[1]);

    if spaceby1 <= int(s[0]):
        box_sum += ((int(s[0])-spaceby1-1)//36 + 1)

    print(box_sum);
Python

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM