2026年3月8日 星期日

ZeroJudge 解題筆記:c110. 00311 - Packets

作者:王一哲
日期:2026年3月8日


ZeroJudge 題目連結:c110. 00311 - Packets

解題想法


如果面積 $6 \times 6$ 的商品數量為 $n_6$,需要的箱子數量就是 $n_6$,而且沒有剩下的空間。 如果面積 $5 \times 5$ 的商品數量為 $n_5$,需要的箱子數量為 $n_5$,每一個箱子會剩下面積為 $11$ 的空間,總空間為 $11 n_5$,可以放入面積 $1 \times 1$ 的商品。 如果面積 $4 \times 4$ 的商品數量為 $n_4$,需要的箱子數量為 $n_4$,每一個箱子會剩下面積為 $20$ 的空間,總空間為 $20 n_4$,可以放入面積 $2 \times 2$ 的商品最多 $5$ 個,如果還有剩下的空間,可以再放入面積 $1 \times 1$ 的商品。下圖的 O 代表可用空間,X 代表已被面積 $4 \times 4$ 商品佔用的空間。
OOOOOO
OOOOOO
XXXXOO
XXXXOO
XXXXOO
XXXXOO
如果面積 $3 \times 3$ 的商品數量為 $n_3$,一個箱子最多可以放入 $4$ 個面積 $3 \times 3$ 的商品,需要的箱子數量 $$ p_3 = \left \lceil \frac{n_3}{4} \right \rceil $$ 如果 $n_3$ 是 $4$ 的倍數,不會有剩下的空間;如果 $mod(n_3, 4) = 1$ 剩下面積為 $27$ 的空間,可以放入面積 $2 \times 2$ 的商品最多 $5$ 個;如果 $mod(n_3, 4) = 2$ 剩下面積為 $18$ 的空間,可以放入面積 $2 \times 2$ 的商品最多 $3$ 個;如果 $mod(n_3, 4) = 3$ 剩下面積為 $9$ 的空間,可以放入面積 $2 \times 2$ 的商品最多 $1$ 個。如果還有剩下的空間,可以再放入面積 $1 \times 1$ 的商品。下圖的 O 代表可用空間,X 代表已被面積 $3 \times 3$ 商品佔用的空間。
OOOOOO     OOOOOO     XXXOOO
OOOOOO     OOOOOO     XXXOOO
OOOOOO     OOOOOO     XXXOOO
XXXOOO     XXXXXX     XXXXXX
XXXOOO     XXXXXX     XXXXXX
XXXOOO     XXXXXX     XXXXXX
如果面積 $2 \times 2$ 的商品數量為 $n_2$,一個箱子最多可以放入 $9$ 個面積 $2 \times 2$ 的商品,需要的箱子數量 $$ p_2 = \left \lceil \frac{n_2}{9} \right \rceil $$ 如果 $n_2$ 是 $9$ 的倍數,不會有剩下的空間;如果 $mod(n_2, 9) = r_2$ 剩下面積為 $36 - 4 r_2$ 的空間,可以放入面積 $1 \times 1$ 的商品。 如果面積 $1 \times 1$ 的商品數量為 $n_1$,一個箱子最多可以放入 $36$ 個面積 $1 \times 1$ 的商品,需要的箱子數量 $$ p_1 = \left \lceil \frac{n_1}{36} \right \rceil $$ 最後答案為 $ans = p_1 + p_2 + p_3 + n_4 + n_5 + n_6$


Python 程式碼


使用時間約為 10 ms,記憶體約為 3.2 MB,通過測試。
import sys

for line in sys.stdin:
    if not line.strip(): continue
    n1, n2, n3, n4, n5, n6 = map(int, line.split())
    if n1 == 0 and n2 == 0 and n3 == 0 and n4 == 0 and n5 == 0 and n6 == 0: break
    """ 放入 5*5 的商品 """
    s5 = 11*n5  # 放 5*5 商品箱子剩下的空間
    if s5 >= n1:  # 可以放入所有 1*1 商品
        s5 -= n1; n1 = 0
    else:  # 無法放入所有 1*1 商品
        n1 -= s5; s5 = 0
    """ 放入 4*4 的商品 """
    s4 = 20*n4  # 放 4*4 商品箱子剩下的空間
    if s4 >= n2*4:  # 可以放入所有 2*2 商品
        s4 -= n2*4; n2 = 0
    else:  # 無法放入所有 2*2 商品
        n2 -= s4//4; s4 = 0
    if s4 > 0 and n1 > 0:  # s4 還有空間而且還有 1*1 商品要放
        if s4 >= n1:  # 可以放入所有 1*1 商品
            s4 -= n1; n1 = 0
        else:  # 無法放入所有 1*1 商品
            n1 -= s4; s4 = 0
    """ 放入 3*3 的商品 """
    r3 = n3%4  # 沒放滿的箱子中 3*3 商品數量
    p3 = n3//4 + (r3 > 0)  # 3*3 商品使用的箱子數量
    s3 = 0  # 沒放滿的箱子剩下的面積
    if r3 == 1:  # 放 1 個 3*3 商品
        s3 = 27  # 面積剩下 27
        if n2 <= 5:  # 可以放入所有 2*2 商品
            s3 -= n2*4; n2 = 0
        else:  # 無法放入所有 2*2 商品
            s3 -= 20; n2 -= 5
    elif r3 == 2:  # 放 2 個 3*3 商品
        s3 = 18  # 面積剩下 18
        if n2 <= 3:  # 可以放入所有 2*2 商品
            s3 -= n2*4; n2 = 0
        else:  # 無法放入所有 2*2 商品
            s3 -= 12; n2 -= 3
    elif r3 == 3:  # 放 3 個 3*3 商品
        s3 = 9  # 面積剩下 9
        if n2 == 1:  # 可以放入所有 2*2 商品
            s3 -= 4; n2 = 0
        elif n2 > 1:  # 無法放入所有 2*2 商品
            s3 -= 4; n2 -= 1
    if s3 > 0 and n1 > 0:  # s3 還有空間而且還有 1*1 商品要放
        if s3 >= n1:  # 可以放入所有 1*1 商品
            s3 -= n1; n1 = 0
        else:  # 無法放入所有 1*1 商品
            n1 -= s3; s3 = 0
    """ 放入 2*2 的商品 """
    r2 = n2%9  # 沒放滿的箱子中 3*3 商品數量
    p2 = n2//9 + (r2 > 0)  # 2*2 商品使用的箱子數量
    s2 = 0 if r2 == 0 else 36 - r2*4  # 沒放滿的箱子剩下的面積
    if s2 > 0 and n1 > 0:  # s2 還有空間而且還有 1*1 商品要放
        if s2 >= n1:  # 可以放入所有 1*1 商品
            s2 -= n1; n1 = 0
        else:  # 無法放入所有 1*1 商品
            n1 -= s2; s2 = 0
    """ 放入 1*1 的商品 """
    p1 = n1//36 + (n1%36 > 0)
    """ 印出答案 """
    print(p1 + p2 + p3 + n4 + n5 + n6)


C++ 程式碼


使用時間約為 1 ms,記憶體約為 52 kB,通過測試。
#include <cstdio>

int main() {
    int n1, n2, n3, n4, n5, n6;
    while(scanf("%d %d %d %d %d %d", &n1, &n2, &n3, &n4, &n5, &n6) != EOF) {
        if (n1 == 0 && n2 == 0 && n3 == 0 && n4 == 0 && n5 == 0 && n6 == 0) break;
        /* 放入 5*5 的商品 */
        int s5 = 11*n5;  // 放 5*5 商品箱子剩下的空間
        if (s5 >= n1) {  // 可以放入所有 1*1 商品
            s5 -= n1; n1 = 0;
        } else {  // 無法放入所有 1*1 商品
            n1 -= s5; s5 = 0;
        }
        /* 放入 4*4 的商品 */
        int s4 = 20*n4;  // 放 4*4 商品箱子剩下的空間
        if (s4 >= n2*4) {  // 可以放入所有 2*2 商品
            s4 -= n2*4; n2 = 0;
        } else {  // 無法放入所有 2*2 商品
            n2 -= s4/4; s4 = 0;
        }
        if (s4 > 0 && n1 > 0) {  // s4 還有空間而且還有 1*1 商品要放
            if (s4 >= n1) {  // 可以放入所有 1*1 商品
                s4 -= n1; n1 = 0;
            } else {  // 無法放入所有 1*1 商品
                n1 -= s4; s4 = 0;
            }
        }
        /* 放入 3*3 的商品 */
        int r3 = n3%4;  // 沒放滿的箱子中 3*3 商品數量
        int p3 = n3/4 + (r3 > 0);  // 3*3 商品使用的箱子數量
        int s3 = 0;  // 沒放滿的箱子剩下的面積
        if (r3 == 1) {  // 放 1 個 3*3 商品
            s3 = 27;  // 面積剩下 27
            if (n2 <= 5) {  // 可以放入所有 2*2 商品
                s3 -= n2*4; n2 = 0;
            } else {  // 無法放入所有 2*2 商品
                s3 -= 20; n2 -= 5;
            }
        } else if (r3 == 2) {  // 放 2 個 3*3 商品
            s3 = 18;  // 面積剩下 18
            if (n2 <= 3) {  // 可以放入所有 2*2 商品
                s3 -= n2*4; n2 = 0;
            } else {  // 無法放入所有 2*2 商品
                s3 -= 12; n2 -= 3;
            }
        } else if (r3 == 3) {  // 放 3 個 3*3 商品
            s3 = 9;  // 面積剩下 9
            if (n2 == 1) {  // 可以放入所有 2*2 商品
                s3 -= 4; n2 = 0;
            } else if (n2 > 1) {  // 無法放入所有 2*2 商品
                s3 -= 4; n2--;
            }
        }
        if (s3 > 0 && n1 > 0) {  // s3 還有空間而且還有 1*1 商品要放
            if (s3 >= n1) {  // 可以放入所有 1*1 商品
                s3 -= n1; n1 = 0;
            } else {  // 無法放入所有 1*1 商品
                n1 -= s3; s3 = 0;
            }
        }
        /* 放入 2*2 的商品 */
        int r2 = n2%9;  // 沒放滿的箱子中 3*3 商品數量
        int p2 = n2/9 + (r2 > 0);  // 2*2 商品使用的箱子數量
        int s2 = (r2 == 0 ? 0 : 36 - r2*4);  // 沒放滿的箱子剩下的面積
        if (s2 > 0 && n1 > 0) {  // s2 還有空間而且還有 1*1 商品要放
            if (s2 >= n1) {  // 可以放入所有 1*1 商品
                s2 -= n1; n1 = 0;
            } else {  // 無法放入所有 1*1 商品
                n1 -= s2; s2 = 0;
            }
        }
        /* 放入 1*1 的商品 */
        int p1 = n1/36 + (n1%36 > 0);
        /* 印出答案 */
        printf("%d\n", p1 + p2 + p3 + n4 + n5 + n6);
    }
    return 0;
}


沒有留言:

張貼留言