POJ1017——裝箱問題


  裝箱問題是...一種很常見的問題。通常描述如下,有編號為1,2,3,4,5...N的N種物品,體積分別為V1,V2....VN。將這N種物品裝到容量都為S的箱子里(箱子容量也可能不同)。約定往這種箱子里裝進去的物品總體積不能超過S,求最少要幾個這種箱子。

問題描述:

  一個工廠制造的產品形狀都是長方體,它們的高度都是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 

————————————————————————————————————————————————————————————————————
  對於這個題目,作為一個菜雞,我首先想到的就是貪心。。大的往里塞就行了,塞不下就用新盒子。。。但是這個是一個二維的裝箱問題。。可以把它理解為一個面積為36的面積,如何用這6種面積的方塊去填滿。
  對於長寬為1的箱子:一個大箱子可以裝36個

  對於長寬為2的箱子:一個大箱子可以裝9個

  對於長寬為3的箱子:一個大箱子可以裝4個

  對於長寬為4、5、6的箱子:一個大箱子可以裝1個,問題就在於這剩下的面積如何擺放是最優的。有最優的就用最優的,沒最優的又該咋個辦。

  我們注意到,長寬為4,5的箱子放進去后,剩余的空間可以用長寬為1,2兩種規格的箱子來填充。一個底面積為4 * 4的箱子進去了,那么剩余的地方可以填充5個2 * 2的箱子,如果2 * 2的箱子不夠可以用1 * 1的箱子來補,1 * 1和2 * 2 都沒有了則需要開新大箱子或者裝完了。而底面積為5 * 5的箱子更簡單了,如果裝了進去那么只能用11個1 * 1的箱子來填。

  還剩下長寬為3的箱子,因為一個大箱子最多可以同時裝4個長寬為3的箱子,如果這種箱子有5個,則需要2個箱子,9個的話需要3個箱子。得出了一個結論,長寬為3的箱子的數目除以4向上取整可以獲取需要的最少大箱子數。那么最后剩下的長寬為3的箱子有可能有1,2,3個。又要分情況處理了。

  剩下一個:剩下27面積,剩下二個:剩下18面積,剩下三個,剩下9面積。這些面積用底面積為1和4的箱子來填充吧!但是我們忽略了一個事實,這個地方還存在着貪心的問題,我們要盡可能的多加進去2*2的箱子,然后最后再考慮1*1的面積。用總面積 - 其他箱子的面積 = 面積為1的箱子的空間。

  終於,我們的問題似乎要解決了,編碼怎么辦....

  

//
//  main.cpp
//  1017
//
//  Created by MadMarical on 15/11/27.
//  Copyright (c) 2015年 com. All rights reserved.
//

#include <iostream>
#include <math.h>

using namespace std;

int main(int argc, const char * argv[])
{
    int boxA,boxB,boxC,boxD,boxE,boxF;//不同底面積箱子數量
    int left2x2,left1x1;
    int countBox;//使用大箱子數量
    
    while(cin>>boxA>>boxB>>boxC>>boxD>>boxE>>boxF)
    {
        //結束條件if (boxA == 0 && boxB == 0 && boxC == 0 && boxD == 0 && boxE == 0 && boxF == 0)
        {
            break;
        }
        //體積為4、5、6的有一個就需要一個箱子,體積為3的需要boxC / 4個箱子
        countBox = boxD + boxF + boxE + (boxC + 3) / 4;
        
        //剩余的空間我們采取貪心的策略,先放2 * 2的箱子,4 * 4的箱子還剩下boxD * 5個2 * 2的空間
        left2x2 = boxD * 5;
        
        //對於3 * 3底面積的需要分情況討論
        if (boxC % 4 == 3) //3 * 3的箱子裝完了還剩下3個,只留下了1個2 * 2的空間
        {
            left2x2 += 1;
        }
        else if (boxC % 4 == 2) //這種情況下留下了3個2 * 2的空間
        {
            left2x2 += 3;
        }
        else if (boxC % 4 == 1) //注意哦,這種情況下最多可以留下5個2 * 2的空間哈
        {
            left2x2 += 5;
        }
        
        if (left2x2 < boxB)
        {
            countBox += (((boxB - left2x2) + 8) / 9);  //2 * 2箱子沒地方的,開新箱子。
        }
        //解決了2 * 2的空間還剩下1 * 1的,總體積減去所有其他箱子的體積,就剩下1 * 1的空間了。
        left1x1 = 36 * countBox - 36 * boxF - 25 * boxE - 16 * boxD - 9 * boxC - 4 * boxB;
        if  (left1x1 < boxA)//空間不夠,加大箱子
        {
            countBox += (((boxA - left1x1) + 35) / 36);
        }
        cout<<countBox<<endl;
    }
    return 0;
}

反思:

1.ceil不知道為啥不行。

2.仔細...是解決一切的王道...

  

  

  


免責聲明!

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



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