結果
| 問題 | No.50 おもちゃ箱 | 
| コンテスト | |
| ユーザー |  lam6er | 
| 提出日時 | 2025-03-31 17:39:38 | 
| 言語 | PyPy3 (7.3.15) | 
| 結果 | 
                                AC
                                 
                             | 
| 実行時間 | 267 ms / 5,000 ms | 
| コード長 | 2,585 bytes | 
| コンパイル時間 | 337 ms | 
| コンパイル使用メモリ | 82,192 KB | 
| 実行使用メモリ | 82,620 KB | 
| 最終ジャッジ日時 | 2025-03-31 17:40:36 | 
| 合計ジャッジ時間 | 4,374 ms | 
| ジャッジサーバーID (参考情報) | judge2 / judge1 | 
(要ログイン)
| ファイルパターン | 結果 | 
|---|---|
| sample | AC * 4 | 
| other | AC * 38 | 
ソースコード
import itertools
def solve():
    import sys
    sys.setrecursionlimit(1 << 25)
    N = int(sys.stdin.readline())
    A = list(map(int, sys.stdin.readline().split()))
    M = int(sys.stdin.readline())
    B = list(map(int, sys.stdin.readline().split()))
    
    max_A = max(A) if N > 0 else 0
    sum_A = sum(A)
    sum_B = sum(B)
    max_B = max(B) if M > 0 else 0
    
    if max_A > max_B or sum_A > sum_B:
        print(-1)
        return
    
    n = len(A)
    sum_mask = [0] * (1 << n)
    for mask in range(1 << n):
        s = 0
        for i in range(n):
            if mask & (1 << i):
                s += A[i]
        sum_mask[mask] = s
    
    for k in range(1, M + 1):
        for boxes in itertools.combinations(B, k):
            if sum(boxes) < sum_A:
                continue
            sorted_boxes = sorted(boxes, reverse=True)
            if sorted_boxes[0] < max_A:
                continue
            target_boxes = sorted_boxes
            
            from functools import lru_cache
            @lru_cache(maxsize=None)
            def backtrack(i, mask):
                if mask == 0 and i == k:
                    return True
                if i >= k:
                    return False
                if mask == 0:
                    return False
                remaining_boxes = k - i
                available_toys = bin(mask).count('1')
                if available_toys < remaining_boxes:
                    return False
                current_cap = target_boxes[i]
                s = mask
                while True:
                    if s == 0:
                        break
                    if (s & mask) != s:
                        s = (s - 1) & mask
                        continue
                    sum_s = sum_mask[s]
                    if sum_s > current_cap:
                        s = (s - 1) & mask
                        continue
                    cnt_s = bin(s).count('1')
                    if cnt_s == 0:
                        s = (s - 1) & mask
                        continue
                    new_mask = mask ^ s
                    remaining_toys = bin(new_mask).count('1')
                    if remaining_toys < (remaining_boxes - 1):
                        s = (s - 1) & mask
                        continue
                    if backtrack(i + 1, new_mask):
                        return True
                    s = (s - 1) & mask
                return False
            
            if backtrack(0, (1 << n) - 1):
                print(k)
                return
    
    print(-1)
solve()
            
            
            
        