[BOJ] #1450 ๋ƒ…์ƒ‰๋ฌธ์ œ (์ด๋ถ„ ํƒ์ƒ‰, Python)

    ๋ฐ˜์‘ํ˜•

    ๐ŸŒฑ ๋ฌธ์ œ

     

    1450๋ฒˆ: ๋ƒ…์ƒ‰๋ฌธ์ œ

    ์ฒซ์งธ ์ค„์— N๊ณผ C๊ฐ€ ์ฃผ์–ด์ง„๋‹ค. N์€ 30๋ณด๋‹ค ์ž‘๊ฑฐ๋‚˜ ๊ฐ™์€ ์ž์—ฐ์ˆ˜, C๋Š” 109๋ณด๋‹ค ์ž‘๊ฑฐ๋‚˜ ๊ฐ™์€ ์Œ์ด ์•„๋‹Œ ์ •์ˆ˜์ด๋‹ค. ๋‘˜์งธ ์ค„์— ๋ฌผ๊ฑด์˜ ๋ฌด๊ฒŒ๊ฐ€ ์ฃผ์–ด์ง„๋‹ค. ๋ฌด๊ฒŒ๋„ 109๋ณด๋‹ค ์ž‘๊ฑฐ๋‚˜ ๊ฐ™์€ ์ž์—ฐ์ˆ˜์ด๋‹ค.

    www.acmicpc.net

     

    ๐ŸŒฑ ํ’€์ด

    1. ๊ธฐ์กด Bruteforce๋กœ ํ’€ ์ˆ˜ ์—†๋Š” ์ด์œ 

    ์ด ๋ฌธ์ œ๋Š” ๋ฌผ๊ฑด์˜ ๊ฐœ์ˆ˜(n)๊ฐ€ ์ตœ๋Œ€ 30๊ฐœ ์ฃผ์–ด์ง‘๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์ด ๋ฌธ์ œ๋ฅผ ์™„์ „ ํƒ์ƒ‰์œผ๋กœ ํ‘ผ๋‹ค๋ฉด ๋ฌผ๊ฑด ํ•˜๋‚˜ํ•˜๋‚˜๋งˆ๋‹ค ๋„ฃ์„์ง€ ์•ˆ๋„ฃ์„์ง€ ๋ชจ๋“  ๊ฒฝ์šฐ๋ฅผ ์„ธ๋ฉด ์ตœ๋Œ€ $2^{30}$๋ฒˆ์˜ ์—ฐ์‚ฐ์„ ํ•˜๊ฒŒ ๋˜๋Š”๋ฐ, ์ด๋Š” 10์–ต์ด ๋„˜๋Š” ๊ฐ’์œผ๋กœ ๋ฌด์กฐ๊ฑด ์‹œ๊ฐ„ ์ดˆ๊ณผ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

    ๊ธฐ์กด Bruteforce๋กœ ํ‘ผ๋‹ค๋ฉด ์ฝ”๋“œ๊ฐ€ ๋‹ค์Œ๊ณผ ๊ฐ™์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

    import sys
    from itertools import combinations
    input = sys.stdin.readline
    
    n, c = map(int, input().split())
    obj = list(map(int, input().split()))
    
    sum_combination = []
    for i in range(0, len(obj) + 1):
        for comb in combinations(obj, i):
            sum_combination.append(sum(comb))
    
    answer = 0
    for sum in sum_combination:
        if sum <= c:
            answer +=1
    print(answer)

    ๋ชจ๋“  ์กฐํ•ฉ์„ ๊ตฌํ•œ ํ›„, ๊ทธ ํ•ฉ์ด ๊ฐ€๋ฐฉ์— ๋„ฃ์„ ์ˆ˜ ์žˆ๋Š” ์ตœ๋Œ€ ๋ฌด๊ฒŒ(c)๋ณด๋‹ค ์ž‘์œผ๋ฉด answer๋ฅผ 1 ์ฆ๊ฐ€์‹œํ‚ต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด ์ฝ”๋“œ๋Š” ๋ฌด์กฐ๊ฑด ์‹œ๊ฐ„์ดˆ๊ณผ๊ฐ€ ๋‚ฉ๋‹ˆ๋‹ค.

     

    2. MITM ์•Œ๊ณ ๋ฆฌ์ฆ˜

    ์ด ๋ฌธ์ œ๋Š” MITM ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•ด์„œ ํ’€์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. MITM ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ Bruteforce๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ ์ด๋ฅผ ๋ถ„ํ• ํ•ด์„œ ์—ฐ์‚ฐ์˜ ์ˆ˜๋ฅผ ์ค„์ด๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์ž…๋‹ˆ๋‹ค. Bruteforce ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•ด์•ผ ํ•˜์ง€๋งŒ ์•ž์„œ ๋งํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ๊ฒฝ์šฐ์˜ ์ˆ˜๊ฐ€ ํด ๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    MITM ์•Œ๊ณ ๋ฆฌ์ฆ˜: "2์‹œ๊ฐ„ ๊ฑฐ๋ฆฌ์— ์‚ด๋˜ ์—ฌ์ž์นœ๊ตฌ๋ฅผ ์‚ฌ๊ท€๋˜ ์‹œ์ ˆ, ๋Œ€๋ถ€๋ถ„ ๋ฐ์ดํŠธ๋ฅผ ์—ฌ์ž์นœ๊ตฌ ๋™๋„ค ์ฃผ๋ณ€์—์„œ ํ–ˆ๋˜ ๊ธฐ์–ต์ด ์žˆ๋‹ค. ์„œ๋กœ ์ง€์ณ์„œ ํ—ค์–ด์งˆ ๋•Œ์ฏค ๋งŒ์•ฝ ์—ฌ์ž์นœ๊ตฌ๊ฐ€ ์ค‘๊ฐ„ ์ง€์ ์—์„œ ์ž์ฃผ ๋งŒ๋‚˜์คฌ๋”๋ผ๋ฉด ์šฐ๋ฆฌ ๊ด€๊ณ„๊ฐ€ ๋” ์˜ค๋ž˜๊ฐ”์„๊นŒ ํ•˜๋Š” ์ƒ๊ฐ์ด ๋ฌธ๋“ ๋“ค์—ˆ์—ˆ๋‹ค."

    n, c = map(int, input().split())
    obj = list(map(int, input().split()))
    left, right = obj[:n//2], obj[n//2:]
    sum_combination_left, sum_combination_right = [], []
    
    for i in range(0, len(left) + 1):
        for sub in combinations(left, i):
            sum_combination_left.append(sum(sub))
    sum_combination_left.sort()
    
    for i in range(0, len(right) + 1):
        for sub in combinations(right, i):
            sum_combination_right.append(sum(sub))
    • MITM ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๋จผ์ € ํƒ์ƒ‰ํ•  ์ž๋ฃŒ๋ฅผ ๋ฐ˜์œผ๋กœ ๋ถ„ํ• ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • ํƒ์ƒ‰ํ•  ์ž๋ฃŒ(obj)๋ฅผ ๋ฐ˜์œผ๋กœ ์ชผ๊ฐœ์„œ, ๋ฐ˜์œผ๋กœ ์ชผ๊ฐ  ๋ฆฌ์ŠคํŠธ์—์„œ ์กฐํ•ฉ์„ ๊ตฌํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ์กฐํ•ฉ์˜ ํ•ฉ์„ ๋ชจ๋‘ ์ƒˆ๋กœ์šด ๋ฆฌ์ŠคํŠธ์— ๋„ฃ์–ด์ค๋‹ˆ๋‹ค. (์ด๊ฒƒ๋งŒ์œผ๋กœ๋„ ์กฐํ•ฉ์˜ ๊ฐœ์ˆ˜๊ฐ€ ํ™•์—ฐํžˆ ์ค„์–ด๋“ค ๊ฒƒ์ž…๋‹ˆ๋‹ค.)
    • ์˜ˆ๋ฅผ ๋“ค์–ด ๋ฌผ๊ฑด์˜ ๊ฐœ์ˆ˜๊ฐ€ 4๊ฐœ์ด๊ณ  ๊ฐ๊ฐ์˜ ๋ฌด๊ฒŒ๊ฐ€ 1, 2, 3, 4๋ผ๋ฉด, ์ „์ฒด ์กฐํ•ฉ์„ ๊ตฌํ•˜๋ฉด ${}_4 C {}_0 + {}_4 C {}_1 + {}_4 C {}_2 + {}_4 C {}_3 + {}_4 C {}_4 = 16$๊ฐœ๊ฐ€ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ ˆ๋ฐ˜์œผ๋กœ ๋ถ„ํ• ํ•˜์—ฌ ์กฐํ•ฉ์„ ๊ตฌํ•˜๋ฉด (1, 2)์˜ ์กฐํ•ฉ 4๊ฐœ, (2, 3)์˜ ์กฐํ•ฉ 4๊ฐœ๋กœ ์ด 8๊ฐœ ๋ฐ–์— ๋‚˜์˜ค์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
      ์ฆ‰, ์—ฐ์‚ฐ์˜ ํšŸ์ˆ˜๊ฐ€ $O(2^n)$์—์„œ $O(2^{\frac{n}{2}})$์œผ๋กœ ์ค„์–ด๋“ค๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

     

    3. ์ด์ง„ํƒ์ƒ‰

    answer = 0
    
    # ์˜ค๋ฅธ์ชฝ ๋ฌผ๊ฑด ๋Œ๋ฉด์„œ ์™ผ์ชฝ ๋ฌผ๊ฑด ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ์˜ ์ˆ˜ ํ•ฉํ•˜๊ธฐ
    for i in sum_combination_right:
        if i > c:
            continue
        start = 0
        end = len(sum_combination_left)
        while start < end:
            mid = (start + end) // 2
            # ์™ผ์ชฝ ๋ฌผ๊ฑด๊ณผ ์˜ค๋ฅธ์ชฝ ๋ฌผ๊ฑด์„ ๋”ํ–ˆ์„ ๋•Œ c๋ณด๋‹ค ํฌ๋ฉด
            if sum_combination_left[mid] + i > c:
                end = mid # ์™ผ์ชฝ ๋ฌผ๊ฑด์—์„œ ๊ฐ€์ ธ์˜ค๋Š” ๋ฌผ๊ฑด์˜ ๋ฌด๊ฒŒ๋ฅผ ์ค„์ด๊ธฐ
            else:
                start = mid + 1 # ์™ผ์ชฝ ๋ฌผ๊ฑด์—์„œ ๊ฐ€์ ธ์˜ค๋Š” ๋ฌผ๊ฑด์˜ ๋ฌด๊ฒŒ ๋Š˜๋ฆฌ๊ธฐ
        answer += end # end ์ธ๋ฑ์Šค์˜ ๊ฐ’์ด ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋Š” ๋ฌผ๊ฑด์˜ ๊ฒฝ์šฐ์˜ ์ˆ˜
    • ์œ„์—์„œ ๋ฐ˜์œผ๋กœ ๋ถ„ํ• ํ•  ์ง€๋ฃŒ์— ๋Œ€ํ•œ ๋ชจ๋“  ์กฐํ•ฉ ๊ฒฝ์šฐ์˜ ํ•ฉ์„ ๋ฆฌ์ŠคํŠธ๋กœ ๋งŒ๋“  ํ›„์—๋Š” ์ด์ง„ํƒ์ƒ‰์œผ๋กœ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋Š” ์กฐํ•ฉ์˜ ๊ฒฝ์šฐ๋ฅผ ์นด์šดํŠธ ํ•ฉ๋‹ˆ๋‹ค.
    • ์ฆ‰, ์˜ค๋ฅธ์ชฝ ๋ฌผ๊ฑด์˜ ๊ฒฝ์šฐ๋ฅผ ํ•˜๋‚˜ ์„ ํƒํ–ˆ์„ ๋•Œ, ์™ผ์ชฝ ๋ฌผ๊ฑด์—์„œ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ์˜ ๊ฐœ์ˆ˜๋ฅผ ์ด์ง„ํƒ์ƒ‰์œผ๋กœ ์ฐพ์Šต๋‹ˆ๋‹ค. 
    • ์™ผ์ชฝ ๋ฌผ๊ฑด์—์„œ ์ด์ง„ํƒ์ƒ‰์„ ํ•ด์•ผ ํ•˜๋ฏ€๋กœ ์™ผ์ชฝ ์กฐํ•ฉ์˜ ํ•ฉ(sum_combination_left)์€ ์ •๋ ฌ์„ ํ•ด์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • ์ผ๋ฐ˜์ ์ธ ์ด์ง„ ํƒ์ƒ‰ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ฒ˜๋Ÿผ ์™ผ์ชฝ ๋ฌผ๊ฑด ์กฐํ•ฉ ๋ฆฌ์ŠคํŠธ(sum_combination_left)์—์„œ start, end, mid ์ธ๋ฑ์Šค๋ฅผ ์„ค์ •ํ•œ ๋’ค, ์™ผ์ชฝ ๋ฌผ๊ฑด์—์„œ ๊ฐ€์ ธ์˜ค๋Š” ๋ฌผ๊ฑด๋“ค์˜ ์กฐํ•ฉ์˜ ํ•ฉ๊ณผ ์˜ค๋ฅธ์ชฝ ๋ฌผ๊ฑด๋“ค์˜ ์กฐํ•ฉ์˜ ํ•ฉ์„ ๋”ํ–ˆ์„ ๋•Œ, c๋ณด๋‹ค ํฌ๋ฉด end๋ฅผ mid๋กœ ์ค„์—ฌ์„œ ์™ผ์ชฝ ๋ฌผ๊ฑด ๋ฆฌ์ŠคํŠธ์—์„œ ๊ฐ€์ ธ์˜ค๋Š” ๋ฌผ๊ฑด์˜ ๋ฌด๊ฒŒ๋ฅผ ์ค„์ด๊ณ , ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์™ผ์ชฝ ๋ฌผ๊ฑด์—์„œ ๊ฐ€์ ธ์˜ค๋Š” ๋ฌผ๊ฑด์˜ ๋ฌด๊ฒŒ๋ฅผ ๋Š˜๋ฆฝ๋‹ˆ๋‹ค.
    • ์ด์ง„ ํƒ์ƒ‰์ด ๋๋‚˜๊ณ  ๋‹ด์„ ์ˆ˜ ์žˆ๋Š” ์ตœ๋Œ€ ๋ฌด๊ฒŒ๋ฅผ ์ฐพ์œผ๋ฉด end ์ธ๋ฑ์Šค์˜ ๊ฐ’์ด ๋‹ค์ ธ์˜ฌ ์ˆ˜ ์žˆ๋Š” ๋ฌผ๊ฑด์˜ ๊ฒฝ์šฐ์˜ ์ˆ˜์ด๋ฏ€๋กœ answer์— ๋”ํ•ด์ค๋‹ˆ๋‹ค.

     

    ๐ŸŒฑ ์ฝ”๋“œ

    # usr/bin/env python
    # -*- coding: utf8 -*-
    # boj 1450 ๋ƒ…์ƒ‰ ๋ฌธ์ œ
    
    import sys
    from itertools import combinations
    input = sys.stdin.readline
    
    n, c = map(int, input().split())
    obj = list(map(int, input().split()))
    left, right = obj[:n//2], obj[n//2:]
    sum_combination_left, sum_combination_right = [0], [0]
    
    if n == 1 and obj[0] <= c:
        print(2)
        exit()
    if n == 1 and obj[0] > c:
        print(1)
        exit()
    
    for i in range(1, len(left) + 1):
        for sub in combinations(left, i):
            sum_combination_left.append(sum(sub))
    sum_combination_left.sort()
    
    for i in range(1, len(right) + 1):
        for sub in combinations(right, i):
            sum_combination_right.append(sum(sub))
    sum_combination_right.sort()
    
    answer = 0
    
    # ์˜ค๋ฅธ์ชฝ ๋ฌผ๊ฑด ๋Œ๋ฉด์„œ ์™ผ์ชฝ ๋ฌผ๊ฑด ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ์˜ ์ˆ˜ ํ•ฉํ•˜๊ธฐ
    for i in sum_combination_right:
        if i > c:
            continue
        start = 0
        end = len(sum_combination_left)
        while start < end:
            mid = (start + end) // 2
            # ์™ผ์ชฝ ๋ฌผ๊ฑด๊ณผ ์˜ค๋ฅธ์ชฝ ๋ฌผ๊ฑด์„ ๋”ํ–ˆ์„ ๋•Œ c๋ณด๋‹ค ํฌ๋ฉด
            if sum_combination_left[mid] + i > c:
                end = mid # ์™ผ์ชฝ ๋ฌผ๊ฑด์—์„œ ๊ฐ€์ ธ์˜ค๋Š” ๋ฌผ๊ฑด์˜ ๋ฌด๊ฒŒ๋ฅผ ์ค„์ด๊ธฐ
            else:
                start = mid + 1 # ์™ผ์ชฝ ๋ฌผ๊ฑด์—์„œ ๊ฐ€์ ธ์˜ค๋Š” ๋ฌผ๊ฑด์˜ ๋ฌด๊ฒŒ ๋Š˜๋ฆฌ๊ธฐ
        answer += end # end ์ธ๋ฑ์Šค์˜ ๊ฐ’์ด ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋Š” ๋ฌผ๊ฑด์˜ ๊ฒฝ์šฐ์˜ ์ˆ˜
    
    print(answer)

     

    +) ์ฐธ๊ณ 

     

    [์•Œ๊ณ ๋ฆฌ์ฆ˜ ๊ธฐ๋ฒ•] Meet In The Middle

    Meet In The Middle ๊ธฐ๋ฒ•(๋ฐฑ์ค€ 1208)

    velog.io

     

    ๋ฐ˜์‘ํ˜•

    ๋Œ“๊ธ€