Skip to main content

SOS_DP

SOS Dynamic Programming

·392 words·2 mins
๐Ÿ“ ์ƒ์„ธ ์ •๋ฆฌ # $2^N$๊ฐœ์˜ ์ •์ˆ˜ ๋ฐฐ์—ด $A$๊ฐ€ ์ฃผ์–ด์ง„๋‹ค. ์ด๋•Œ $\forall x$ ์— ๋Œ€ํ•ด $F(x)$๋ฅผ $\sum\limits_{i \subseteq x}{A[i]}$ ๋ผ๊ณ  ์ •์˜ํ•˜์ž. ์ด๋Š” $x\&i = i$ ์ธ $i$๋“ค์— ๋Œ€ํ•ด $A[i]$์˜ ํ•ฉ์„ ์˜๋ฏธํ•œ๋‹ค. ์œ„์™€ ๊ฐ™์€ ๋ฌธ์ œ๋ฅผ ์–ด๋–ป๊ฒŒ ํ’€ ์ˆ˜์žˆ์„๊นŒ? ๋ธŒ๋ฃจํŠธํฌ์Šค # ๋А๋ฆฌ์ง€๋งŒ, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ธŒ๋ฃจํŠธํฌ์Šค๋กœ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ๊ฒ ๋‹ค. for(int mask = 0; mask < (1<<N); mask++){ for(int i = 0; i < (1<<N); i++){ if((mask&i) == i){ F[mask] += A[i]; } } } ์œ„ ์‹์„ ๊ทธ๋Œ€๋กœ ์˜ฎ๊ธด ๊ฒƒ์— ๊ฐ€๊น๋‹ค. ์‹œ๊ฐ„๋ณต์žก๋„๋Š” ${(2^N)}^2 = 4^N$์ด๋‹ค. ์กฐ๊ธˆ ๋” ๋‚˜์€ ํ’€์ด # ๋‘๋ฒˆ์งธ ๋ฐ˜๋ณต๋ฌธ์— ๋Œ€ํ•ด, ๋ฐ”๊นฅ์ชฝ ๋ฐ˜๋ณต๋ฌธ์—์„œ ์ผœ์ง€์ง€ ์•Š์€ ๋น„ํŠธ์— ๋Œ€ํ•ด์„œ๋„ ๋ฐ˜๋ณต์„ ๋„๋Š”๊ฒƒ์€ ๋„ˆ๋ฌด ์•„๊น๋‹ค. ๋”ฐ๋ผ์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด๋„ ํ•œ๋ฒˆ ์‹œ๋„ํ•ด๋ณผ ์ˆ˜ ์žˆ๊ฒ ๋‹ค. for(int mask = 0; mask < (1<<N); mask++){ F[mask] = A[0]; for(int i = 0; i < (1<<N); i = (i-1)&mask) F[mask] += A[i]; } ์‹œ๊ฐ„๋ณต์žก๋„ ์ฆ๋ช…์ด ์–ด๋ ค์›Œ๋ณด์ธ๋‹ค. ์ด๋Š” $\sum\limits_{k = 0}^N{\binom{N}{K}2^K} = 3^N$ ์ด๋ผ๊ณ  ํ•œ๋‹ค. Sum over Subsets DP # ์œ„์˜ ๋ฐฉ์‹์—์„œ ๋ณ‘๋ชฉ์€ ์–ด๋””์—์„œ ๋‚˜ํƒ€๋‚ ๊นŒ? ์–ด๋–ค $x$์˜ ๋น„ํŠธ๊ฐ€ $K$๊ฐœ๊ฐ€ ๊บผ์ ธ์žˆ์„ ๋•Œ, $A[x]$๋Š” $2^K$๊ฐœ์˜ ๋งˆ์Šคํฌ์— ์˜ํ•ด ๋ฐฉ๋ฌธ๋œ๋‹ค. ์ด ๋ฐ˜๋ณต์ ์ธ ์žฌ๊ณ„์‚ฐ์„ ์ค„์—ฌ์•ผํ•œ๋‹ค. S(mask, i) ์ •์˜ # ์œ„ ๋ณ‘๋ชฉ์„ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด ์ƒˆ๋กœ์šด ์ƒํƒœ๋ฅผ ํ•˜๋‚˜ ์ •์˜ํ•ด๋ณด์ž. $S(mask, i)$๋Š” $mask$์˜ ๋ถ€๋ถ„์ง‘ํ•ฉ๋“ค ์ค‘, $mask$์™€ ํ•˜์œ„(์˜ค๋ฅธ์ชฝ) $i$๊ฐœ ๋น„ํŠธ(0~i-1๋ฒˆ ์ธ๋ฑ์Šค)์—์„œ๋งŒ ๋‹ค๋ฅธ ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, $S(110, 2) = \{100, 110\}$์ด๋‹ค. ์˜ค๋ฅธ์ชฝ ๋‘๊ฐœ ๋น„ํŠธ์—์„œ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ๋Š”๋ฐ, ๋ถ€๋ถ„์ง‘ํ•ฉ์ด์–ด์•ผ ํ•˜๋ฏ€๋กœ $111$๊ฐ™์€๊ฑด ์•ˆ๋œ๋‹ค. ์ด ์ •์˜๋ฅผ ์ด์šฉํ•˜๋ฉด, ์–ด๋–ค ์ง‘ํ•ฉ๋„ ์„œ๋กœ ๊ฒน์น˜์ง€ ์•Š๋Š” $S(mask, i)$๋“ค์˜ ํ•ฉ์ง‘ํ•ฉ์œผ๋กœ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค. ์ ํ™”์‹ ์œ ๋„ # ์ ํ™”์‹์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋‘๊ฐ€์ง€๋กœ ์ •์˜ํ•  ์ˆ˜ ์žˆ๊ฒ ๋‹ค. $mask$์˜ $i$๋ฒˆ์งธ ๋น„ํŠธ๊ฐ€ $0$์ธ ๊ฒฝ์šฐ $mask$์˜ ๋ถ€๋ถ„์ง‘ํ•ฉ์ด $i$๋ฒˆ์งธ ๋น„ํŠธ์—์„œ $0$๋งŒ์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ $S(mask, i) = S(mask, i-1)$ $mask$์˜ $i$๋ฒˆ์งธ ๋น„ํŠธ๊ฐ€ $1$์ธ ๊ฒฝ์šฐ $mask$์˜ ๋ถ€๋ถ„์ง‘ํ•ฉ์ด $i$๋ฒˆ์งธ ๋น„ํŠธ์—์„œ $0, 1$ ๋ชจ๋‘ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ $S(mask, i) = S(mask, i-1) \cup S(mask \oplus 2^i, i-1)$ ๋”ฐ๋ผ์„œ ์ด๋ฅผ ์ฝ”๋“œ๋กœ ๋‚˜ํƒ€๋‚ด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค. for(int mask = 0; mask < (1<<N); mask++) DP[mask] = A[mask]; for(int i = 0; i<N; i++){ for(int mask = 0; mask < (1<<N); mask++){ if(mask & (1<<i)) DP[mask] += DP[mask ^ (1<<i)]; } } ๊ณ„์‚ฐ ๊ฒฐ๊ณผ DP์— ๋“ค์–ด์žˆ๋Š” ๊ฐ’์€ ํ•ด๋‹น ๋น„ํŠธ๋งˆ์Šคํ‚น์˜ ๋ถ€๋ถ„์ง‘ํ•ฉ์˜ ํ•ฉ์ด๋‹ค. ์‹œ๊ฐ„๋ณต์žก๋„๋Š” ๊ทธ๋Œ€๋กœ ๋ณด์ด๋“ฏ์ด $O(N2^N)$์ด๋‹ค. N์ฐจ์› ๋ˆ„์ ํ•ฉ # https://blog.queuedlab.com/posts/sos-dp ๋ฅผ ์ฐธ๊ณ ํ•˜๋ฉด, ์ด๋ฅผ $N$์ฐจ์› ๋ˆ„์ ํ•ฉ์œผ๋กœ๋„ ํ•ด์„ํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ดํผ ์ˆ˜์—ด๊ณผ ํ•˜์ดํผ ์ฟผ๋ฆฌ ๋ฌธ์ œ์—์„œ $N$์ฐจ์› ๋ˆ„์ ํ•ฉ ์•„์ด๋””์–ด๋Š” ์จ๋ณธ์ ์ด ์žˆ์—ˆ๋Š”๋ฐ, ์ด๊ฒƒ์ด SOS DP์™€ ๊ฐ™๋‹ค๋Š” ๊ฒƒ์ด ์‹ ๊ธฐํ•˜๋‹ค. ์•ž์œผ๋กœ๋Š” ํฌํ•จ๋ฐฐ์ œ์—์„œ ๋ญ”๊ฐ€ ์ค„์ด๊ณ ์‹ถ์œผ๋ฉด ํ•œ๋ฒˆ์”ฉ์€ ์˜์‹ฌํ•ด๋ณด๋Š”๊ฑธ๋กœ? imos-hanbyul Trick # ์ด์™€ ๋น„์Šทํ•œ ๋‚ด์šฉ์„ https://qwerasdfzxcl.tistory.com/35 ์—ฌ๊ธฐ์„œ ๋ณธ์ ์ด ์žˆ๋‹ค. ์ง€๊ธˆ ๋‹น์žฅ์€ ์ดํ•ดํ•˜๊ธฐ ๊ท€์ฐฎ์œผ๋ฏ€๋กœ ์ดํ•ดํ•œ ๋‚ด์šฉ์€ ๋‚˜์ค‘์— ์ถ”๊ฐ€ํ•˜๊ฒ ๋‹ค. โ”์งˆ๋ฌธ ์‚ฌํ•ญ # ๐Ÿ”— ์ฐธ๊ณ  ์ž๋ฃŒ # https://codeforces.com/blog/entry/45223 https://blog.queuedlab.com/posts/sos-dp https://qwerasdfzxcl.tistory.com/35

BOJ 2803 ๋‚ด๊ฐ€ ์–ด๋ ธ์„ ๋•Œ ๊ฐ€์ง€๊ณ  ๋†€๋˜ ์žฅ๋‚œ๊ฐ

·401 words·2 mins
๐Ÿ“ ๋ฌธ์ œ ์ •๋ณด # ๋งํฌ: https://www.acmicpc.net/problem/2803 ๐Ÿง ๊ด€์ฐฐ ๋ฐ ์ ‘๊ทผ # ๋น„ํŠธ๋งˆ์Šคํ‚น์ ์œผ๋กœ ์ ‘๊ทผํ•ด๋ณด๋ฉด, ์—ฌ๋Ÿฌ ์žฅ๋‚œ๊ฐ ์ƒ์ž๋“ค์˜ or ์—ฐ์‚ฐ๊ฒฐ๊ณผ๊ฐ€ $1111111..$์ด ๋˜๋„๋ก ํ•˜๋Š” ์กฐํ•ฉ์˜ ๊ฐœ์ˆ˜๋ฅผ ์ฐพ์œผ๋ฉด ๋˜๋Š” ๊ฒƒ ๊ฐ™๋‹ค. $N$์— ๋Œ€ํ•ด ์ƒ๊ฐํ•˜๊ธด ๊นŒ๋‹ค๋กœ์šฐ๋ฏ€๋กœ, $M \leq 20$์ธ ๊ฒƒ์„ ์ด์šฉํ•ด์„œ $M$์— ๋Œ€ํ•œ ๋น„ํŠธ๋งˆ์Šคํ‚น๋œ ์ƒ์ž์˜ ์ˆ˜๋กœ ์ƒ๊ฐํ•ด๋ณด์ž. ์ดํ›„ ๊ณผ์ •์„ ํฌํ•จ๋ฐฐ์ œ๋กœ ์ง„ํ–‰ํ•˜๋ฉด $O(2^N \times 2^N)$์ด๊ฒ ์ง€๋งŒ, ์šฐ๋ฆฌ๋Š” SOS DP๋ฅผ ์ด์šฉํ•ด์„œ $O(N2^N)$ ์— ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ์Œ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ๊ทธ๋ƒฅ ๊ธฐ๋ณธ์ ์ธ SOS DP๋ž‘์€ ์„ธํŒ…์ด ์กฐ๊ธˆ ๋‹ค๋ฅธ๊ฐ€? ๊ณ ๋ฏผํ•ด๋ณด์ž. ๊ธฐ๋ณธ์ ์ธ SOS DP๋Š” ํ•ด๋‹น ๋น„ํŠธ๋งˆ์Šคํฌ์˜ ๋ถ€๋ถ„์ง‘ํ•ฉ์˜ ์›์†Œ ๊ฐœ์ˆ˜์˜ ํ•ฉ์ด๋‹ค. ์ด๋ฒˆ์— ๊ตฌํ•ด์•ผํ•˜๋Š”๊ฑด ํ•ด๋‹น ๋น„ํŠธ๋งˆ์Šคํฌ๋ฅผ ๋งŒ๋“ค์–ด์ค„ ์ˆ˜ ์žˆ๋Š” ์กฐํ•ฉ์˜ ๊ฐœ์ˆ˜์ธ๋ฐ.. ๊ฒฐ๊ตญ ์–ด๋–ค ์ƒ์ž $110011$์„ ๊ณจ๋ž๋‹ค๊ณ  ์ƒ๊ฐํ•ด๋ณด์ž. ๊ทธ๋Ÿฌ๋ฉด, $??11??$ ์ธ๊ฑธ ๋ชจ๋‘ ๊ณ ๋ฅด๋ฉด ๋œ๋‹ค. ์ด๊ฑธ ๋ถ€๋ถ„์ง‘ํ•ฉ์œผ๋กœ ์„ธ๊ธด ํž˜๋“ค์ง€๋งŒ, ๋’ค์ง‘์–ด์„œ ์ƒ๊ฐํ•œ๋‹ค๋ฉด $??00??$์„ ์ฐพ๋Š” ๊ฒƒ์ด๊ณ , ์ด๊ฑด $110011$์˜ ๋ถ€๋ถ„์ง‘ํ•ฉ์˜ ๊ฐœ์ˆ˜์™€ ๊ฐ™์€ ๊ฒƒ ๊ฐ™๋‹ค! ์ž๊ธฐ ์ž์‹ ์„ ์„ธ์ง€ ์•Š๋„๋ก ์กฐ์‹ฌํ•˜์ž. ๊ทธ๋Ÿฐ๋ฐ ์ € ๋ฐฉ๋ฒ•์œผ๋กœ ์„ธ๋ฉด, ๋‘๊ฐœ์˜ or์—ฐ์‚ฐ๋ฐ–์— ๊ณ ๋ คํ•˜์ง€ ๋ชปํ•œ๋‹ค… 3๊ฐœ ์ด์ƒ์ธ๊ฑธ ๊ณ ๋ คํ•˜๋ ค๋ฉด DP ์„ค๊ณ„๋ฅผ ์กฐ๊ธˆ ๋” ์ž˜ํ•ด์•ผ ํ•  ๊ฒƒ ๊ฐ™๋‹ค. ์•„ํ•˜, ์›๋ž˜๊ฒŒ $??11??$์ธ ๊ฐœ์ˆ˜๋ฅผ ์•ˆ๋‹ค๋ฉด, ์—ฌ๊ธฐ์—์„œ ํ•œ๊ฐœ ์ด์ƒ๋งŒ ๊ณ ๋ฅด๋ฉด ๋œ๋‹ค. ๊ทธ ๊ฐœ์ˆ˜๋ฅผ $\text{cnt}$๋ผ๊ณ  ํ•˜๋ฉด, $2^{\text{cnt}} - 1$์ด ์„ฑ๋ฆฝํ•˜๋Š”๊ฑฐ ๊ฐ™๊ธฐ๋„? ๊ทผ๋ฐ ๋‹ค์‹œ ์ƒ๊ฐํ•ด๋ณด๋‹ˆ, ๋ญ๋ž„๊นŒ ์›๋ž˜๊ฐ€ $??10??$$ ์ธ๊ฑฐ๋ž‘ $??01??$$ ์ธ๊ฑฐ๋ž‘์ด ํ•ฉ์ณ์ ธ์„œ ๋˜๋Š”๊ฒƒ๋“ค์„ ๋ชป์„ธ๋Š”๊ฑฐ..๊ฐ™๊ธฐ๋„? ์—ฐ์‚ฐํ•ด์„œ $11$์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด์„ , $(11 + 10 + 01 + 00)^2$ ๊ฐ™์€ ๋А๋‚Œ์œผ๋กœ ์ƒ๊ฐํ•ด๋ณด์ž. ์ € ์—ฐ์‚ฐ ๊ฒฐ๊ณผ๋Š” $$ 11^2 + 10^2 + 01^2 + 00^2 + \\ 2(11\cdot10 + 11\cdot01 + 11\cdot00 + 10\cdot01 + 10\cdot00 + 01\cdot00) $$ ์ด๊ณ , ์ž˜ ๊ณ ๋ฏผํ•ด๋ณด๋‹ˆ $11$์˜ ๋ถ€๋ถ„์ง‘ํ•ฉ์˜ ์ œ๊ณฑ - $11, 01$์˜ ๋ถ€๋ถ„์ง‘ํ•ฉ์˜ ์ œ๊ณฑ - $00$์˜ ๋ถ€๋ถ„์ง‘ํ•ฉ์˜ ์ œ๊ณฑ์„ ํ•˜๋ฉด ๊น”๋”ํ•˜๊ฒŒ $11^2 + 2(11\times10 + 11\times01 + 11\times00 + 10\times01)$์ด ๋œ๋‹ค. ์•„๋‹ˆ ์ž ๊น๋งŒ, ์ € ๋А๋‚Œ์„ ๊ทธ๋Œ€๋กœ ๊ฐ€์ ธ๊ฐ€๋ฉด ๊ทธ๋ƒฅ ๋ถ€๋ถ„์ง‘ํ•ฉ์˜ ํ•ฉ์œผ๋กœ SOS DP๋ฅผ ํ•œ๋‹ค์Œ์— ํฌํ•จ๋ฐฐ์ œ๋ฅผ ๋•Œ๋ ค๋ฒ„๋ฆฌ๋ฉด ์–ด๋–ป๊ฒŒ๋“  ๋œ๋‹ค. ์—ฐ์‚ฐ๊ฒฐ๊ณผ๊ฐ€ $11...11$์ธ๋†ˆ๋“ค - $(01...11), (10..111)...$ + $...$ ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋˜๋Š”๊ตฌ๋‚˜! ๐Ÿ’ป ํ’€์ด # ์ฝ”๋“œ (C++): void solve(){ int N, M; cin >> N >> M; vector<int> A(N); rep(i, 0, N){ int K; cin >> K; int ret = 0; rep(j, 0, K){ int x; cin >> x; ret |= (1 << (x-1)); } A[i] = ret; } vector<int> SOS(1 << M, 0); for(auto x: A) SOS[x] += 1; rep(i, 0, M) rep(mask, 0, 1<<M) if(mask & (1 << i)) SOS[mask] += SOS[mask^(1<<i)]; mint ans = 0; rep(mask, 0, 1<<M){ int cnt = 0; rep(i, 0, M) if((mask & (1 << i)) == 0) cnt++; if(cnt & 1) ans -= (mint(2).pow(SOS[mask])); else ans += (mint(2).pow(SOS[mask])); } cout << ans << "\n"; } ๐Ÿ”’ ๊ตฌํ˜„ ์ฝ”๋“œ ์ž ๊ธˆ