Search
Duplicate
๐Ÿ˜€

07. [DP] 0-1 Knapsack

ํƒœ๊ทธ
DP

0-1 Knapsack

๋„๋‘‘์ด ๋ณด์„๊ฐ€๊ฒŒ์— ๋ฐฐ๋‚ญ์„ ๋ฉ”๊ณ  ์นจ์ž…ํ–ˆ๋‹ค. ๋ฐฐ๋‚ญ์˜ ์ตœ๋Œ€ ์šฉ๋Ÿ‰์€ W์ด๋ฉฐ, ์ด๋ฅผ ์ดˆ๊ณผํ•ด์„œ ๋ณด์„์„ ๋‹ด์œผ๋ฉด ๋ฐฐ๋‚ญ์ด ์ฐข์–ด์งˆ ๊ฒƒ์ด๋‹ค. ๊ฐ ๋ณด์„๋“ค์˜ ๋ฌด๊ฒŒ์™€ ๊ฐ€๊ฒฉ์€ ์•Œ๊ณ  ์žˆ๋‹ค. ๋ฐฐ๋‚ญ์ด ์ฐข์–ด์ง€์ง€ ์•Š๋Š” ์•Š๋Š” ์„ ์—์„œ ๊ฐ€๊ฒฉ ํ•ฉ์ด ์ตœ๋Œ€๊ฐ€ ๋˜๋„๋ก ๋ณด์„์„ ๋‹ด๋Š” ๋ฐฉ๋ฒ•์€?

์ƒ๊ฐํ•  ์ˆ˜ ์žˆ๋Š” ์‹œํ–‰์ฐฉ์˜ค

1) ๋ชจ๋“  ๊ฒฝ์šฐ์˜ ์ˆ˜๋ฅผ ๋„ฃ์–ด๋ณธ๋‹ค (Brute-Force)
n๊ฐœ์˜ ๋ณด์„์ด ์žˆ๋‹ค๊ณ  ์น˜๋ฉด, n๊ฐœ ๋ณด์„์œผ๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ๊ฐ€๋Šฅํ•œ ๋ถ€๋ถ„์ง‘ํ•ฉ (power set) ์˜ ์ˆ˜๋Š” 2^n๊ฐœ์ด๋‹ค. ์ตœ์•…์˜ ๊ฒฝ์šฐ์— 2^n๋ฒˆ๊นŒ์ง€ ๋ด์•ผ ํ•˜๋Š”, ์ฆ‰ O(2^n) ์˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ๋„ˆ๋ฌด ๋Š๋ฆฌ๋‹ค.
2) ๊ฐ€๊ฒฉ์ด ๋†’์€ ๋ณด์„, ํ˜น์€ (๊ฐ€๊ฒฉ/๋ฌด๊ฒŒ) ์˜ ๊ฐ’์ด ์ œ์ผ ๋†’์€ ๋ณด์„๋ถ€ํ„ฐ ๋จผ์ € ๊ณจ๋ผ์„œ ๋„ฃ๋Š”๋‹ค (Greedy)
์•„๋ž˜์˜ ๊ทธ๋ฆผ์„ ๋ณด์ž. ๊ฐ€๊ฒฉ์ด ์ œ์ผ ๋†’์€ ๋ณด์„์„ ๋จผ์ € ๊ณ ๋ฅด๋Š” ๋ฐฉ๋ฒ•์„ ์“ด๋‹ค๊ณ  ํ•˜๋ฉด, ์˜ค๋ฅธ์ชฝ ์•„๋ž˜์— ์žˆ๋Š” ๋นจ๊ฐ„ ๋ณด์„์„ ๋จผ์ € ๊ณ ๋ฅด๊ณ  ๊ทธ ๋‹ค์Œ ์™ผ์ชฝ์— ์žˆ๋Š” ๋…ธ๋ž€ ๋ณด์„์„ ๊ณ ๋ฅผ ๊ฒƒ์ด๋‹ค. ๊ทธ๋Ÿด ๊ฒฝ์šฐ์— ๊ฐ€๊ฒฉ์˜ ์ดํ•ฉ์€ 16์ด ๋œ๋‹ค.
ํ•˜์ง€๋งŒ 1, 2, 3, 4์˜ ๋ฌด๊ฒŒ๋ฅผ ์„ ํƒํ•˜์˜€์„ ๋•Œ์˜ ๊ฐ€๊ฒฉ์€ ์ดํ•ฉ์€ 19๊ฐ€ ๋‚˜์˜ค๊ณ  ๋‹จ์ˆœํ•˜๊ฒŒ ๊ฐ€๊ฒฉ์ด ๋†’์€ greedyํ•œ ๋ฐฉ๋ฒ•์„ ๊ณ ๋ คํ–ˆ์„ ๋•Œ ๋‹ต์„ ๊ตฌํ•  ์ˆ˜ ์—†๋‹ค.
'๋ฌด๊ฒŒ๋‹น ๊ฐ€๊ฒฉ'์„ ๊ณ„์‚ฐํ•ด์„œ ์ œ์ผ ๋†’์€ ๊ฒƒ๋ถ€ํ„ฐ ์ง‘์–ด ๋„ฃ์œผ๋ฉด ์„ฑ๋ฆฝํ•  ๊ฒƒ ๊ฐ™๋‹ค๋Š” ์ƒ๊ฐ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค. ์‹ค์ œ๋กœ ์œ„์˜ ๊ทธ๋ฆผ์—์„œ๋Š” ๊ทธ๋ ‡๊ฒŒ ์ˆ˜ํ–‰ํ•˜๋ฉด ์ตœ์ ์˜ ๋‹ต์ด ๋‚˜์˜จ๋‹ค. ํ•˜์ง€๋งŒ ์–ธ์ œ๋‚˜ ๊ทธ๋ ‡์ง€๋Š” ์•Š๋‹ค. ์•„๋ž˜์˜ ์˜ˆ์‹œ๋ฅผ ๋ณด์ž
์ด ๊ฒฝ์šฐ์— '๋ฌด๊ฒŒ๋‹น ๊ฐ€๊ฒฉ' ์ˆœ์œผ๋กœ ๋ณด์„์„ ๋„ฃ์œผ๋ฉด ๋ณด์„1, ๋ณด์„3์ด ๋“ค์–ด๊ฐ€๋ฉฐ ๊ฐ€๊ฒฉ์˜ ํ•ฉ์€ 19์ด๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ๋ฐฐ๋‚ญ ๋ฌด๊ฒŒ๊ฐ€ 5๊ฐ€ ๋‚จ๋Š”๋‹ค. ๋ณด์„2๋ฅผ ๋„ฃ์„ ์ˆ˜๋Š” ์—†์œผ๋ฏ€๋กœ 5๋Š” ๊ทธ๋ƒฅ ์“ธ๋ฐ์—†์ด ๋‚จ๋Š” ๊ณต๊ฐ„์ด๋‹ค.
๋ณด์„2, ๋ณด์„3์„ ๋„ฃ์œผ๋ฉด 30๋ฌด๊ฒŒ๋ฅผ ๊ฐ€๋“ ์ฑ„์šฐ๊ณ  ๊ฐ€๊ฒฉ์˜ ํ•ฉ์ด 20์ด๋‹ค. ๋„๋‘‘ ์ž…์žฅ์—์„œ ๋„๋ง๊ฐˆ ๋•Œ ๋ฐฐ๋‚ญ์ด ์ข€ ๋” ๋ฌด๊ฑฐ์šธ ์ˆ˜ ์žˆ๊ฒ ์ง€๋งŒ ์–ด์จŒ๋“  ๋ฌธ์ œ์˜ ์กฐ๊ฑด์€ ๋ฐฐ๋‚ญ์ด ์•ˆ ํ„ฐ์ง€๋Š” ํ•œ๋„ ๋‚ด์—์„œ ๊ฐ€๊ฒฉ ํ•ฉ์„ ์ตœ๋Œ€ํ™”ํ•˜๋Š” ๊ฒƒ์ด๋ฏ€๋กœ ๋ณด์„2, 3์„ ๊ฐ€์ ธ๊ฐ€๋Š” ๊ฒƒ์ด ์ •๋‹ต์ด๋‹ค.
์ด์ฒ˜๋Ÿผ ํŠน์ •ํ•œ ๊ธฐ์ค€์„ ์ •ํ•ด๋†“๊ณ  ๊ทธ ๊ธฐ์ค€์˜ ๊ฐ’์ด ๊ฐ€์žฅ ๋†’์€ ์ˆœ์œผ๋กœ ์ง‘๋Š” ๊ฑธ Greedy ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด๋ผ ํ•˜๋Š”๋ฐ 0-1 ๋ฐฐ๋‚ญ ์ฑ„์šฐ๊ธฐ ๋ฌธ์ œ๋Š” Greedyํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ๋Š” ํ’€ ์ˆ˜ ์—†๋Š” ๋ฌธ์ œ์ด๋‹ค.
Fractional Knapsack ๋ฌธ์ œ๋Š” Greedy๋กœ ํ’€ ์ˆ˜ ์žˆ๋‹ค. ์œ„ ์˜ˆ์‹œ์—์„œ ๋ณด์„2๋ฅผ ๋ฐ˜์œผ๋กœ ์ž˜๋ผ์„œ ๋‚จ์€ 5kg์งœ๋ฆฌ ๊ณต๊ฐ„์— ๋„ฃ์œผ๋ฉด ๊ทธ๊ฒŒ ์ตœ์ ์˜ ๋‹ต์ด ๋œ๋‹ค

DP์˜ ์ ์šฉ

์–ด๋–ค ๋ฌธ์ œ๋ฅผ DP๋กœ ํ’€๊ธฐ ์œ„ํ•ด์„œ๋Š” '์ตœ์ ์˜ ์›๋ฆฌ' (Principle of Optimality) ๊ฐ€ ์„ฑ๋ฆฝํ•˜๋Š”์ง€๋ฅผ ํ™•์ธํ•ด์•ผ ํ•˜๋Š”๋ฐ, ์ตœ์ ์˜ ์›๋ฆฌ๋ž€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.
"์–ด๋–ค ๋ฌธ์ œ์˜ ์ž…๋ ฅ์‚ฌ๋ก€์˜ ์ตœ์ ํ•ด๊ฐ€ ๊ทธ ์ž…๋ ฅ์‚ฌ๋ก€๋ฅผ ๋ถ„ํ• ํ•œ ๋ถ€๋ถ„์‚ฌ๋ก€์— ๋Œ€ํ•œ ์ตœ์ ํ•ด๋ฅผ ํ•ญ์ƒ ํฌํ•จํ•˜๊ณ  ์žˆ์œผ๋ฉด, ๊ทธ ๋ฌธ์ œ์— ๋Œ€ํ•˜์—ฌ ์ตœ์ ์˜ ์›๋ฆฌ๊ฐ€ ์„ฑ๋ฆฝํ•œ๋‹ค."
์ด ๋ฌธ์ œ์—์„œ ์ด ์›๋ฆฌ๊ฐ€ ์„ฑ๋ฆฝํ• ๊นŒ? ์ง‘ํ•ฉ A๋ฅผ n๊ฐœ์˜ ๋ณด์„๋“ค ์ค‘์— ์ตœ์ ์œผ๋กœ ๊ณ ๋ฅธ ๋ถ€๋ถ„์ง‘ํ•ฉ์ด๋ผ๊ณ  ๊ฐ€์ •ํ•˜์ž.
โ€ข
์ง‘ํ•ฉ A๊ฐ€ n๋ฒˆ์งธ ๋ณด์„์„ ํฌํ•จํ•˜๊ณ  ์žˆ์ง€ ์•Š๋‹ค๋ฉด, A๋Š” n๋ฒˆ์งธ ๋ณด์„์„ ๋บ€ ๋‚˜๋จธ์ง€ n-1๊ฐœ์˜ ๋ณด์„๋“ค ์ค‘์—์„œ ์ตœ์ ์œผ๋กœ ๊ณ ๋ฅธ ๋ถ€๋ถ„์ง‘ํ•ฉ๊ณผ ๊ฐ™๋‹ค.
โ€ข
์ง‘ํ•ฉ A๊ฐ€ n๋ฒˆ์งธ ๋ณด์„์„ ํฌํ•จํ•˜๊ณ  ์žˆ๋‹ค๋ฉด, A์— ์†ํ•œ ๋ณด์„๋“ค์˜ ์ด ๊ฐ€๊ฒฉ์€ n-1๊ฐœ์˜ ๋ณด์„๋“ค ์ค‘์—์„œ ์ตœ์ ์œผ๋กœ ๊ณ ๋ฅธ ๊ฐ€๊ฒฉ์˜ ํ•ฉ์—๋‹ค๊ฐ€ ๋ณด์„ n์˜ ๊ฐ€๊ฒฉ์„ ๋”ํ•œ ๊ฒƒ๊ณผ ๊ฐ™๋‹ค. (๋‹จ, n๋ฒˆ์งธ ๋ณด์„์„ ๋„ฃ์—ˆ์„ ๋•Œ ๋ฐฐ๋‚ญ์ด ํ„ฐ์ง€์ง€ ์•Š์•„์•ผ ํ•œ๋‹ค)
์ ํ™”์‹์œผ๋กœ ํ’€์–ด๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค.
P[i, w] ๋ž€ i๊ฐœ์˜ ๋ณด์„์ด ์žˆ๊ณ  ๋ฐฐ๋‚ญ์˜ ๋ฌด๊ฒŒ ํ•œ๋„๊ฐ€ w์ผ ๋•Œ ์ตœ์ ์˜ ์ด์ต์„ ์˜๋ฏธํ•œ๋‹ค. ์‹์„ ์ข€ ๋ฌธ์žฅ์œผ๋กœ ํ’€์–ด๋ณด๋ฉด ์ด๋ ‡๋‹ค.
โ€ข
i๋ฒˆ์งธ ๋ณด์„์ด ๋ฐฐ๋‚ญ์˜ ๋ฌด๊ฒŒ ํ•œ๋„๋ณด๋‹ค ๋ฌด๊ฑฐ์šฐ๋ฉด ๋„ฃ์„ ์ˆ˜ ์—†์œผ๋ฏ€๋กœ i๋ฒˆ์งธ ๋ณด์„์„ ๋บ€ i-1๊ฐœ์˜ ๋ณด์„๋“ค์„ ๊ฐ€์ง€๊ณ  ๊ตฌํ•œ ์ „ ๋‹จ๊ณ„์˜ ์ตœ์ ๊ฐ’์„ ๊ทธ๋Œ€๋กœ ๊ฐ€์ ธ์˜จ๋‹ค
โ€ข
๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ, i๋ฒˆ์งธ ๋ณด์„์„ ์œ„ํ•ด i๋ฒˆ์งธ ๋ณด์„๋งŒํผ์˜ ๋ฌด๊ฒŒ๋ฅผ ๋น„์› ์„ ๋•Œ์˜ ์ตœ์ ๊ฐ’์— i๋ฒˆ์งธ ๋ณด์„์˜ ๊ฐ€๊ฒฉ์„ ๋”ํ•œ ๊ฐ’ or i-1๊ฐœ์˜ ๋ณด์„๋“ค์„ ๊ฐ€์ง€๊ณ  ๊ตฌํ•œ ์ „ ๋‹จ๊ณ„์˜ ์ตœ์ ๊ฐ’ ์ค‘ ํฐ ๊ฒƒ์„ ์„ ํƒํ•œ๋‹ค

ํ’€์ด ๊ณผ์ •

i == 0 || w == 0
๊ณ ๋ คํ•˜๋Š” ๋ณด์„์ด 0๊ฐœ, ๋ฐฐ๋‚ญ์— ์ง‘์–ด๋„ฃ๋Š” ๋ฌด๊ฒŒ๊ฐ€ 0์ธ ์ƒํƒœ์ด๋‹ค. ๋ชจ๋‘ 0์œผ๋กœ๋งˆํ‚นํ•œ ์ƒํƒœ์—์„œ ์‹œ์ž‘ํ•œ๋‹ค.
i == 1
i=1์ธ ๊ฒฝ์šฐ๋ถ€ํ„ฐ ํ•œ์นธ์”ฉ ๋ณด์ž. (i, w)๊ฐ€ (1, 1) ์ธ ๊ฒฝ์šฐ์—๋Š” w=1์งœ๋ฆฌ ๋ฐฐ๋‚ญ์œผ๋กœ๋Š” ์•„๋ฌด ๋ณด์„๋„ ๋„ฃ์„ ์ˆ˜ ์—†์œผ๋ฏ€๋กœ 0์ด๋‹ค. ๊ทธ ๋‹ค์Œ ์นธ, (1, 2) ์ธ ๊ฒฝ์šฐ์—๋Š” ์ด์ œ 1๋ฒˆ ๋ณด์„์„ ๋„ฃ์„ ์ˆ˜ ์žˆ์œผ๋‹ˆ๊นŒ V[1, 2] = 3์ด ๋œ๋‹ค.
์ง๊ด€์ ์œผ๋กœ๋Š” ์ด๋ ‡๊ณ , ์œ„์˜ ์‹์„ ํ†ตํ•ด์„œ ๋ณด๋ฉด '1๋ฒˆ ๋ณด์„์˜ ๊ฐ€์น˜ + V[0, 0]' ์˜ ๊ฐ’๊ณผ V[0, 2] ์˜ ๊ฐ’์„ ๋น„๊ตํ•ด์„œ ๋” ํฐ ์ชฝ์„ ๊ฐ€์ ธ๊ฐ€๊ฒŒ ๋˜๋Š”๋ฐ, 1๋ฒˆ ๋ณด์„์˜ ๊ฐ€์น˜๋Š” 3์ด๊ณ  V[0, 0] ๊ณผ V[0, 2] ๋Š” ๋‘˜ ๋‹ค 0์ด๋ฏ€๋กœ ์ „์ž๋ฅผ ์„ ํƒํ•˜๊ฒŒ ๋œ๋‹ค.
i == 2
i=2์ธ ๊ฒฝ์šฐ๋ฅผ ๋ณด๋ฉด, w=2์ผ๋•Œ๋Š” ํ˜„์žฌ ๋ณด๊ณ ์žˆ๋Š” 2๋ฒˆ ๋ณด์„ (3kg) ์„ ๋„ฃ์„ ์ˆ˜ ์—†์œผ๋ฏ€๋กœ ๋ฐ”๋กœ ์œ—์นธ์˜ 3์„ ๊ฐ€์ ธ์˜จ๋‹ค (1๋ฒˆ ๋ณด์„์„ ๋„ฃ๋Š”๋‹ค๋Š” ๋œป). w=3์ด ๋˜๋ฉด 2๋ฒˆ ๋ณด์„์„ ๋„ฃ์„ ์ˆ˜ ์žˆ๊ฒŒ ๋˜๋Š”๋ฐ, 1๋ฒˆ ๋ณด์„์„ ๋„ฃ์—ˆ์„ ๋•Œ (๋ฐ”๋กœ ์œ—์นธ) ๋ž‘ 2๋ฒˆ ๋ณด์„์„ ๋„ฃ์„๋งŒํผ์˜ ๊ณต๊ฐ„์„ ํ™•๋ณดํ•˜๊ณ  2๋ฒˆ ๋ณด์„์„ ๋„ฃ์—ˆ์„ ๋•Œ (์ฆ‰, 2๋ฒˆ ๋ณด์„์˜ ๊ฐ€์น˜ + V[1, 0]) ๋ฅผ ๋น„๊ตํ•ด์„œ ๋” ๊ฐ€์น˜๊ฐ€ ๋†’์€ ์ชฝ์„ ์„ ํƒํ•œ๋‹ค. ๊ทธ๋ž˜์„œ 4๊ฐ€ ๋“ค์–ด๊ฐ„๋‹ค.
๋ชจ๋“  ๊ณผ์ • ์ˆ˜ํ–‰ ์ดํ›„

์ฝ”๋“œ ์ž‘์„ฑ

public class FruitNotFoundException extends Exception { public FruitNotFoundException(String name) { super(name + "์— ํ•ด๋‹นํ•˜๋Š” ๊ณผ์ผ์€ ์—†์Šต๋‹ˆ๋‹ค."); } public static void main(String[] args) { Scanner sc = new Scanner(System.in); int N = sc.nextInt(); int W = sc.nextInt(); int[] weights = new int[N+1]; int[] profits = new int[N+1]; for(int i = 1; i <= N; i++) { weights[i] = sc.nextInt(); profits[i] = sc.nextInt(); } int[][] D = new int[N+1][N+1]; for(int i = 1; i<=N; i++) { for(int w = 1; w <= W; w++) { if(weights[i] <= w) { // ํ•ด๋‹น ๋ณด์„์„ ๊ฐ€๋ฐฉ์— ๋„ฃ์„ ์ˆ˜ ์žˆ๋‹ค. D[i][w] = Math.max(D[i-1][w], profits[i] + D[i-1][w - weights[i]]); }else { // ํ•ด๋‹น ๋ณด์„์„ ๊ฐ€๋ฐฉ์— ๋„ฃ์„ ์ˆ˜ ์—†๋‹ค. D[i][w] = D[i-1][w]; } } } } }
Java
๋ณต์‚ฌ

0-1 knapsack์˜ 1์ฐจ์› ๋ฐฐ์—ด ํ’€์ด

DP์„ bottom-up์˜ ์ƒํ–ฅ์‹ ํ’€์ด๋กœ ํ’€์—ˆ์„ ๋•Œ DP[w]์˜ ๊ฐ’์€ DP[w - i] ์˜ ๊ฐ’์„ ์ฐธ์กฐํ•˜๋ฉฐ ์ฑ„์›Œ์ง€๊ฒŒ ๋œ๋‹ค. i๋ฒˆ์งธ ๋ณด์„์˜ ์ฒ˜๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” i-1๋ฒˆ์งธ ๋ณด์„๊นŒ์ง€์˜ ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š”๋ฐ i๋ฒˆ์งธ ๋ณด์„์˜ ์ฒ˜๋ฆฌ ๊ณผ์ •์—์„œ i - 1 ๋ฒˆ์งธ ๊ฐ’์„ ๋ฎ์–ด์”Œ์šด๋‹ค๋ฉด ์˜ฌ๋ฐ”๋ฅธ ์ •๋‹ต์„ ๊ตฌํ•  ์ˆ˜ ์—†๋‹ค.
๋”ฐ๋ผ์„œ bottom-up ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด 2์ฐจ์› ๋ฐฐ์—ด์„ ๊ด€๋ฆฌํ•ด์„œ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ์˜ฌ๋ฐ”๋ฅธ ์ •๋‹ต์„ ๊ตฌํ•  ์ˆ˜ ์—†๋‹ค.
ํ•˜์ง€๋งŒ top-down์˜ ํ•˜ํ–ฅ์‹ ํ’€์ด๋กœ ํ‘ธ๋Š” ๊ฒฝ์šฐ์—” ์œ„์™€ ๊ฐ™์€ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.
์œ„์ฒ˜๋Ÿผ n์ฐจ์› ๋ฐฐ์—ด DP๋ฅผ n-1 ์ฒ˜๋Ÿผ ์ตœ์ ํ™” ํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์ด ํ”Œ๋กœ์ด๋“œ-์™€์ƒฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜์—๋„ ์ ์šฉ๋œ๋‹ค.