intro
๐ backtracking์ด๋, ํ์ฌ ์ํ์์ ๊ฐ๋ฅํ ๋ชจ๋ ํ๋ณด๊ตฐ์ ๋ฐ๋ผ ๋ค์ด๊ฐ๋ฉฐ ํ์ํ๋ ์๊ณ ๋ฆฌ์ฆ. ๊ตฌํ๋ ฅ์ ํ์๋ก ํ๋ค. ํ์ฌ์์ ๋์ฌ ์ ์๋ ๋ชจ๋ ๊ฒฝ์ฐ์ ์๋ฅผ ๋ชจ์ ๋ decision space๋ฅผ ๋ง๋ค๊ณ , decision space์ ๊ฐ ๋ถ๋ถ๋ง๋ค ๋ป์ด ๋๊ฐ๋ฉฐ ๊ทธ ๋ค์์ผ๋ก ๋์ค๋ deicision space์์ ๊ณ์ํด์ ๋ป์ด๋๊ฐ๋ฉฐ ํ์. ๋ง์ฝ ๋ป์ด๋๊ฐ ๊ฒฐ๊ณผ ๋ฌธ์ ์ํฉ์ ๋ง์ง ์์ผ๋ฉด, ๊ทธ ์๋ฆฌ์์ ์ค๋จํ๊ณ ๋ค์ ๋ค๋ก ํํดํ๋ฉด์ ์ฌ๋ผ๊ฐ ๋ ๋ค๋ฅธ ๊ฒฝ์ฐ์ ์๋ก ๋ป์ด๋๊ฐ๋ฉฐ ํ์.
๐ ์ฆ, ์์ฝํ์๋ฉด ์ฌ๊ท์ ์ผ๋ก ๊ฐ๋ฅํ ๋ชจ๋ case๋ฅผ incrementallyํ๊ฒ ํ์ํด๋๊ฐ๋ฉด์ ํด๋น ๋ฌธ์ ์กฐ๊ฑด์ ๋ง์กฑํ์ง ์๋ ๊ฒฝ์ฐ๋ ์ด์ ์ผ๋ก ๋์๊ฐ(backtrack) ๊ณ์ ์๋ฃจ์
์ ์ฐพ๋ ๊ธฐ๋ฒ(๊ฒฐ๋ก : ๋ฐฑํธ๋ํน์ ๊ทธ๋ฅ ๋ฌธ์ ๋ง์ด...). DFS์ ๋ค๋ฅธ ์ ์, DFS๋ ๋ชจ๋ case๋ฅผ ๊ฒ์ํ๋ฉฐ ๋ป์ด๋๊ฐ์ง๋ง, backtracking์ ๋ป์ด๋๊ฐ๋ ๋์ค ๋ง์ง ์๋๋ค๋ฉด ๊ฒ์ ์์ด ๋ฐ๋ก ์ค๋จ. ๋ฐ๋ผ์ ๋ฐฑํธ๋ํน์ด๋ผ๋ฉด ์ด๋ฏธ ์ง๋์ณ์จ ๊ณณ์ ๋ค์ ๋์๊ฐ์ ๋ค๋ฅธ ๊ฐ๋ฅ์ฑ์ ์๋ํด๋ณด๋ ์๊ณ ๋ฆฌ์ฆ์ผ๋ก, ๋ฌด์์ ๋ชจ๋ case๋ฅผ ์ผ์ผ์ด ํ์ธํ๋ brute-force์๋ ์ฐจ์ด๊ฐ ์๋ค. backtracking์ ๊ณผ๊ฑฐ์ ๋ฏธ๋ ์ํ๋ฅผ ๋ชจ๋ ๊ณ ๋ คํ์ฌ ๋ป์ด๋๊ฐ๊ฑฐ๋ ๊ฐ์ง์น๊ธฐํ๋ ํ์ ์๊ณ ๋ฆฌ์ฆ์ผ๋ก brute-force๋ณด๋ค ์ฑ๋ฅ์ด ๋ ์ข์ผ๋ฉฐ, ์ด ๋ ์ฌ๊ท๊ฐ ๊ธฐ๋ณธ์ ์ผ๋ก ์ฐ์ธ๋ค. ๋ฐ๋ผ์ ๊ตฌํ์ด ์๋นํ ์ด๋ ต..
backtracking example
โ N๊ณผ M ๊ธฐ์ด((1) ~ (8))
๐ ๋ํ ๋ฌธ์ BOJ N๊ณผ M (1)์ ์์ฝํ๋ฉฐ backtracking ์ฌ๊ท์ ์ต์ํด์ง์.
โป BOJ 15649 N๊ณผ M (1)
Q. ์์ฐ์ N๊ณผ M์ด ์ฃผ์ด์ก์ ๋, ์๋ ์กฐ๊ฑด์ ๋ง์กฑํ๋ ๊ธธ์ด๊ฐ M์ธ ์์ด ๋ชจ๋ ๊ตฌํ๊ธฐ
์กฐ๊ฑด โ ) ์ค๋ณต๋๋ ์์ด์ ๋ฑ 1๋ฒ๋ง ์ถ๋ ฅ
์กฐ๊ฑด โก) ์์ด์ ์ฌ์ ์์ผ๋ก ์ฆ๊ฐํ๋ ์์๋ก ์ถ๋ ฅ
(์ด ๋ 1๋ถํฐ N๊น์ง์ ์์ฐ์์์ ์์ด ๋ง๋ค๊ธฐ)
(1)
→ track()๊ณผ backtrack ์ฅ์น๋ฅผ ๊ฐ๊ฐ ๊ธฐ์ตํด์ฃผ๋ฉด ๋๋ค. track()์ด๋ผ๋ ์๋๋ก ๋ด๋ ค๊ฐ๋ ํ๋์ ํ์ดํ๋ฅผ ๋ฐ๋ณต์ ์ผ๋ก ์ฌ์ฉํ๋ฏ๋ก recursion
→ ๋ ๊ฐ์ง ์ข ๋ฅ์ backtracking โ ๋์ค์ ์กฐ๊ฑด์ ๋ง์ง ์์ ๋ฐ๋ก ์๋ก ์ฌ๋ผ๊ฐ๋ backtracking / โก ์ ๋ต์ ๋ชจ๋ ๊ตฌํด ํด๋น case๊ฐ ๋ค ๋๋ ๋ค์ ์ฌ๋ผ๊ฐ๋ backtracking: ์ด ๋ ๋ค์ ์ฌ๋ผ๊ฐ๊ธฐ ์ํด์ ์ ์์์ ๊ฐ์ด ans.pop()๊ณผ ๊ฐ์ ์ฅ์น track() ์ดํ ๋ง๋ค์ด์ค์ผ ํ๋ค.
N,M=map(int,input().split())
ans=[]
def track():
if len(ans) == M: #completed
print(*ans)
else:
for x in range(1,N+1):
if len(ans) != 0 and x in ans:
continue #backtrack 1
else:
ans.append(x)
track()
ans.pop() #backtrack 2
track()
: ํจ์ ๋๋๋ if๋ฌธ → ๊ทธ๋ ์ง ์๋ค๋ฉด backtrack 1 ๋ฐ๋ก ํ ๊ฒ์ธ์ง if๋ฌธ → backtrack1 ์ํ๋ค๋ฉด track() ๋ด๋ ค๊ฐ๊ธฐ + track() ๋ด๋ ค๊ฐ๊ธฐ ์ดํ ์ฌ๋ผ๊ฐ๊ธฐ ์ฝ๋
(2)
→ ๋๋, ๋์ค์ ๊ฐ์ง์น๊ธฐ ๋๋ backtracking์ ๋ช ์์ ์ผ๋ก continue๋ฌธ ๊ตฌํ ํ์ ์์ด track() ๋๋ ๋ถ๋ถ๋ง ๋๋ ค / ๋ต์ ๊ตฌํ๊ณ ๋ ๋ค ์ญ ์ฌ๋ผ๊ฐ๋ backtrack ์ฅ์น๋ง ๋ง๋ค์ด๋ OK
N,M=map(int,input().split())
ans=[]
def track():
if len(ans) == M: #completed
print(*ans)
else:
for x in range(1,N+1):
if len(ans) == 0 or x not in ans:
ans.append(x)
track()
ans.pop() #backtrack
track()
โก N๊ณผ M ์ฌํ((9)~(12))
โป BOJ 15663 N๊ณผ M (9)
Q. ์์ฐ์ N๊ณผ M์ด ์ฃผ์ด์ก์ ๋, ์๋ ์กฐ๊ฑด์ ๋ง์กฑํ๋ ๊ธธ์ด๊ฐ M์ธ ์์ด ๋ชจ๋ ๊ตฌํ๊ธฐ
์กฐ๊ฑด โ ) ์ค๋ณต๋๋ ์์ด์ ๋ฑ 1๋ฒ๋ง ์ถ๋ ฅ
์กฐ๊ฑด โก) ์์ด์ ์ฌ์ ์์ผ๋ก ์ฆ๊ฐํ๋ ์์๋ก ์ถ๋ ฅ
(์ด ๋ ์ค๋ณต์ ํฌํจํ,๋๋คํ N๊ฐ์ ์์ฐ์์์ ์์ด ๋ง๋ค๊ธฐ)
๐ ์ฌ๊ท์ ์ผ๋ก ๋๋ backtracking์์ ์ฃผ์ด์ง ๋ฐฐ์ด์์ ์์ฐ์๋ ์ต๋ 1๋ฒ๋ง ์ฐ์ด๊ณ ์์ด ์ค๋ณต ๋ฐฉ์ง๋ฅผ ์ํด ์์ ๊ธฐ์ด backtracking์์ ์ฅ์น๋ฅผ ๋ช ๊ฐ์ง ๋ ๋ง๋ค์ด์ฃผ์ด์ผ ํ๋ค. (1) visited [] ์ฌ์ฉํ์ฌ not visitedํ ๊ณณ๋ง ์ฌ๊ท ์งํ. ์ด ๋ ์ฌ๊ท ์ visited = True ์ค์ ํ๊ณ , ์ฌ๊ท ํจ์ ์๋ซ์ค, ์ฆ ์ฌ๊ท ์ดํ์๋ pop()๊ณผ ํจ๊ป visited = False ๊ผญ ์ค์ ํ์ (์ด์ ์ํ๋ก ๋๋๋ฆฌ๊ธฐ์ด๋ฏ๋ก) / (2) ์์ด ์ค๋ณต ๋ฐฉ์ง๋ฅผ ์ํด ๋ฐ๋ก ์์ ์์, ์ฆ ๋ง์ง๋ง ์์ last๋ง ๋น๊ตํ๋ฉด ๋๋ค. ๊ทธ ์ด์ ๋ ์ฌ๊ท์ ํน์ฑ์, ๋ฐ๋ก ์์ ์์์ ๊ฐ์ง ์๋ค๋ฉด ๊ทธ ์๋ ์ญ ํ์์ ์ํด์ฃผ๊ธฐ ๋๋ฌธ.
import sys
input=sys.stdin.readline
N,M=map(int,input().split())
nums=list(map(int,input().split()))
nums.sort()
num,visited=[],[False]*N
def track():
if len(num)==M:
print(*num)
else:
last=0
for i in range(len(nums)):
if not visited[i] and last!=nums[i]:
visited[i]=True
num.append(nums[i])
last=nums[i]
track()
num.pop()
visited[i]=False
track()
โข N๊ณผ M BOJ ์ ๋ฆฌ
Q. N๊ฐ์ ์์ฐ์ ์ค์ ์กฐ๊ฑด์ ๋ง์กฑํ๋ M๊ฐ์ ์์ด์ ์ถ๋ ฅํ๋ ๋ฌธ์
'Computer Science > Algorithms' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๐ก Two Pointers (1) | 2024.02.11 |
---|---|
๐ฆ Pigeonhole Principle (0) | 2024.02.02 |
๐งฟ Dijkstra's (Shortest Path) Algorithm (1) | 2024.01.14 |
๐LIS(Longest Increasing Subsequence) O(n^2)/O(nlogn) (0) | 2024.01.06 |
๐กKadane's Algorithm (0) | 2024.01.03 |
๋๊ธ