๐Ÿค”์•Œ๊ณ ๋ฆฌ์ฆ˜

[์•Œ๊ณ ๋ฆฌ์ฆ˜] - ๋ฐฐ๋‚ญ๋ฌธ์ œ(Knapsack Problem)

์—ฌ์šฐ๋น„_YoBi 2024. 9. 3. 22:19

๋ฐฐ๋‚ญ๋ฌธ์ œ๋ž€?

๋ฐฐ๋‚ญ ๋ฌธ์ œ๋Š” ์ฃผ์–ด์ง„ ์ œํ•œ๋œ ์šฉ๋Ÿ‰์˜ ๋ฐฐ๋‚ญ์— ์ตœ๋Œ€ํ•œ์˜ ๊ฐ€์น˜๋ฅผ ๊ฐ€์ง„ ์•„์ดํ…œ์„ ๋„ฃ๋Š” ๋ฐฉ๋ฒ•์„ ์ฐพ๋Š” ๋ฌธ์ œ๋ฅผ ์˜๋ฏธํ•œ๋‹ค. 

n๊ฐœ์˜ ๋ฌผ๊ฑด์˜ ๋ฌด๊ฒŒw์™€ ๊ฐ€์น˜ v์— ์ฃผ์–ด์งˆ ๋•Œ, ์šฉ๋Ÿ‰์ด k์ธ ๋ฐฐ๋‚ญ์˜ ์šฉ๋Ÿ‰์„ ์ดˆ๊ณผํ•˜์ง€ ์•Š๊ณ  ๋‹ด์„ ์ˆ˜ ์žˆ๋Š” ์ตœ๋Œ€์˜ ๊ฐ€์น˜๋ฅผ ์ฐพ๋Š” ๋ฌธ์ œ์ด๋‹ค. 

๋ฐฐ๋‚ญ๋ฌธ์ œ์˜ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

  • ๋ชจ๋“  ๊ฒฝ์šฐ ํƒ์ƒ‰ (brute-force)
    • ๋ฌผ๊ฑด์„ ๋‹ด๋Š”๋‹ค/๋‹ด์ง€ ์•Š๋Š”๋‹ค์˜ ๊ฒฝ์šฐ๋ฅผ ์ƒ๊ฐํ•˜์—ฌ 2^n์˜ ๋ชจ๋“  ์กฐํ•ฉ์„ ํƒ์ƒ‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์‹œ๊ฐ„ ๋ณต์žก๋„๊ฐ€ ๋„ˆ๋ฌด ์ปค์„œ n๊ฐ’์ด ํฐ ๊ฒฝ์šฐ์—๋Š” ํ•ด๊ฒฐํ•  ์ˆ˜ ์—†๋‹ค. 
  • ํƒ์š•์  ์•Œ๊ณ ๋ฆฌ์ฆ˜ (Greedy)
    • ๋‹จ์œ„ ๋ฌด๊ฒŒ๋‹น ๋†’์€ ๊ฐ€์น˜๋ถ€ํ„ฐ ๋‹ด๋Š” ๋ฐฉ๋ฒ•.
    • ๋ถ„ํ•  ๋ฐฐ๋‚ญ ๋ฌธ์ œ์—์„œ๋Š” ํšจ์œจ์ ์œผ๋กœ ๋™์ž‘ํ•œ๋‹ค. 
  • ๋™์  ํ”„๋กœ๊ทธ๋ž˜๋ฐ (Dynamic Programming)
    • ์ฃผ์–ด์ง„ ์•„์ดํ…œ๊ณผ ๋ฐฐ๋ƒฅ์˜ ์šฉ๋Ÿ‰์„ ์ด์šฉํ•ด ๊ฐ€๋Šฅํ•œ ๊ฐ€์น˜์˜ ์กฐํ•ฉ์„ ๊ณ„์‚ฐ
  • ๋ธŒ๋žœ์น˜ ์•ค ๋ฐ”์šด๋“œ (Branch and Bound) 
    • ๋ฌธ์ œ์˜ ํƒ์ƒ‰๊ณต๊ฐ„์„ ํšจ์œจ์ ์œผ๋กœ ์ค„์—ฌ๊ฐ€๋ฉฐ(๊ฐ€์ง€ ์น˜๊ธฐ) ์ตœ์ ํ•ด๋ฅผ ํƒ์ƒ‰

๋ฐฐ๋‚ญ๋ฌธ์ œ with Dynamic Programming

๋ฌผ๊ฑด๊ณผ ๋ฐฐ๋‚ญ์˜ ์šฉ๋Ÿ‰์„ ๋‚˜ํƒ€๋‚ด๋Š” DP 2์ฐจ์› ๋ฐฐ์—ด์„ ์„ ์–ธํ•œ๋‹ค. 

dp[i][w] : ์ฒซ i๊ฐœ์˜ ์•„์ดํ…œ ์ค‘์—์„œ ์ตœ๋Œ€ w๊นŒ์ง€์˜ ๋ฌด๊ฒŒ๋ฅผ ๊ณ ๋ คํ–ˆ์„ ๋•Œ ์–ป์„ ์ˆ˜ ์žˆ๋Š” ์ตœ๋Œ€์˜ ๊ฐ€์น˜

 

  • dp[i][w] = dp[i-1][w] 
    • ์•„์ดํ…œ i๋ฅผ ์„ ํƒํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ, ์ด์ „ i-1๊ฐœ์˜ ์•„์ดํ…œ์œผ๋กœ ๊ตฌ์„ฑ๋œ ์ตœ๋Œ€ ๊ฐ€์น˜์™€ ๋™์ผํ•จ. 
  • dp[i][w] = max(dp[i-1][w], dp[i-1][w-weight[i]] + values[i] )
    • ์•„์ดํ…œ i๋ฅผ ์„ ํƒํ•˜๋Š” ๊ฒฝ์šฐ์™€ ์„ ํƒํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ์ค‘ ๊ฐ€์น˜๊ฐ€ ๋” ๋†’์€ ๊ฒƒ์„ ์„ ํƒ

๋ฐฐ๋‚ญ๋ฌธ์ œ with Dynamic Programming ์ฝ”๋“œ

def knapsack_dp(values, weights, W):
	n = len(values)
    dp = [[0 for _ in range(W+1)] for _ in range(n+1)]
    
    for i in range(1, n+1):
    	for w in range(1, W+1):
        	# ๋ฐฐ๋‚ญ์— ํ•ด๋‹น ์•„์ดํ…œ์„ ๋„ฃ์„ ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ
        	if weights[i-1] <= w:
            	# ์•„์ดํ…œ์„ ๋„ฃ์ง€ ์•Š์•˜์„ ๊ฒฝ์šฐ์™€, ์•„์ดํ…œ์„ ๋„ฃ์–ด์„œ ๋ฐฐ๋‚ญ์˜ ์šฉ๋Ÿ‰์ด ์ค„๊ณ  ๊ฐ€์น˜๊ฐ€ ๋Š˜์–ด๋‚˜๋Š” ๊ฒƒ ์ค‘ ์ตœ๋Œ€๊ฐ’ ์„ ํƒ
            	dp[i][w] = max(dp[i-1][w], dp[i-1][w-weight[i-1]] + values[i-1])
            # ๋ฐฐ๋‚ญ์— ํ•ด๋‹น ์•„์ดํ…œ์„ ๋„ฃ์„ ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ
            else:
            	dp[i][w] = dp[i-1][w]
    return dp[n][w]