https://www.acmicpc.net/problem/1941
1941번: 소문난 칠공주
총 25명의 여학생들로 이루어진 여학생반은 5×5의 정사각형 격자 형태로 자리가 배치되었고, 얼마 지나지 않아 이다솜과 임도연이라는 두 학생이 두각을 나타내며 다른 학생들을 휘어잡기 시작
www.acmicpc.net
0. 문제
5x5 형태로 S(이다솜파) Y(이도연파) 값이 input이 주어진다.
격자에서 7명을 뽑되, 다음 조건을 만족시키는 경우의 수 개수를 구하라.
- 7명을 뽑고 이들은 모두 인접해있어야 한다.
- S는 4명 이상 뽑아야 한다.
1. 아이디어
현재 위치에서 하나씩 요소를 추가해나가면 되기 때문에 DFS / BFS 를 생각하기 쉽다.
하지만 베이직한 DFS / BFS 는 마지막 위치에서 4방향 중 한 쪽으로만 전파하기 때문에 위와 같이 Y에서 양쪽을 선택해야 하는 경우를 선택할 수 없다. 이를 해결하기 위해서, 지금까지 선택했던 경로에서 4방향으로의 전파를 모두 확인해야 한다.
이 때, 방문체크는 선택한 루트를 기준으로 해줘야한다.
예를 들어 [(0, 0), (1, 0)] 를 순서대로 선택한 경우와 [(1, 0), (0, 0)] 를 순서대로 선택한 경우 결과는 동일하다. 그래서 루트가 동일하면 더 이상 재귀하지 않도록 return 을 해야한다. 나는 set을 이용하여 이미 저장된 경로를 확인했다.
2. 구현
dr = [-1, 1, 0, 0]
dc = [0, 0, -1, 1]
def func(route, Y_member):
global result
# 가지 치기 => 임도연 파가 4명 이상되면 X
if Y_member >= 4:
return
# route를 저장해두고, 이미 방문한 경우면 return
tuple_route = tuple(sorted(route))
if tuple_route in route_check:
return
else:
route_check.add(tuple_route)
# 종료 => 7명을 모두 픽했으면 종료
if len(route) == 7:
result += 1
return
# 재귀 => 모든 route 포인트에서 4방향으로 전파할 수 있다
for r, c in route:
for i in range(4):
nr = r + dr[i]
nc = c + dc[i]
# 범위 바깥이거나 이미 방문한 곳
if not (0 <= nr < 5 and 0 <= nc < 5) or ((nr, nc) in route):
continue
# 갈 수 있는 곳
if IN[nr][nc] == 'Y':
func(route + [(nr, nc)], Y_member + 1)
else:
func(route + [(nr, nc)], Y_member)
IN = [list(input()) for _ in range(5)]
result = 0
route_check = set()
for r in range(5):
for c in range(5):
Y_member = 1 if IN[r][c] == 'Y' else 0
func([(r, c)], Y_member)
print(result)
'APS > BOJ' 카테고리의 다른 글
[Python / BOJ 9944] NxM 보드 완주하기 (0) | 2022.09.04 |
---|---|
[Python / BOJ 1248] Guess (0) | 2022.08.30 |
[Python / BOJ 2661] 좋은 수열 (0) | 2022.08.04 |
[Python / BOJ 2239] 스토쿠 (0) | 2022.07.29 |
[Python / BOJ 20440] 니가 싫어 싫어 너무 싫어 싫어 오지 마 내게 찝쩍대지마 (0) | 2022.06.19 |