[BOJ_Python]1941. 소문난 칠공주
2024. 10. 15. 14:13ㆍ[Algorithm]/문제 풀이
문제
https://www.acmicpc.net/problem/1941
사용 알고리즘
BFS, Backtracking, BruteForce
풀이
고려사항
1. 인원 7명 모으기
2. 이다솜파(S)의 수가 4이상인지 확인
3. 모인 7명의 인접여부 확인
후기
1. 이 문제의 keypoint는 학생을 인덱스화하여 백트레킹을 진행하는 것이다.
idx = [(i, j) for j in range(5) for j in range(5)]
인덱스화를 하여 지금 위치 이후 학생들을 기준으로 재귀를 진행했고
이 방식을 사용하면 동일한 학생 집단의 중복이 없다.
처음에 다른 방식으로 한 학생을 기준으로 잡고 7명을 모은 경우
다른 학생을 기준으로 7명을 잡은 경우와 중복되어 동일한 집단이 겹치는 경우가 발생했다.
이것을 확인하는 것에 시간이 많이 사용되어 시간초과를 초래할 수 있어
이러한 중복이 발생되지 않도록 인덱스 방식을 선택하였다.
2. 또한,인접여부 확인 전 이다솜파의 수를 확인을 먼저 진행하도록 하여 상대적으로 무거운 인접여부 작업 횟수를 줄였다.
3. bfs의 경우 방문 리스트를 따로 두어
bfs를 모두 마쳤을 때 7군데 모두 방문여부를 확인하였다.
코드
import sys
from collections import deque
input = sys.stdin.readline
didj = [(0, 1), (1, 0), (0, -1), (-1, 0)]
def bfs(members):
visited = [False for _ in range(7)]
q = deque([members[0]])
while q:
ci, cj = q.popleft()
for di, dj in didj:
ni, nj = ci + di, cj + dj
if 0 <= ni < 5 and 0 <= nj < 5:
for i in range(7):
if visited[i] == False and (ni, nj) == members[i]:
visited[i] = True
q.append((ni, nj))
# 7명 모두 방문했는지 확인(인접여부)
if visited.count(False) == 0:
return True
return False
# 7명 모으기 위한 재귀 진행
def group(members, depth):
global cnt
# 7명 모인 경우 소문난 칠공주 결성 여부 확인
if len(members) == 7:
# 이다솜파가 4명 이상인지 확인
s = 0
for i, j in members:
if students[i][j] == "S":
s += 1
if s < 4:
return
# 인접여부 확인
if bfs(members):
# 모두 확인 된 경우 cnt 1 증가
cnt += 1
return
for cur in range(depth, 25):
members.append(idx[cur])
group(members, cur + 1)
members.pop()
return
students = [list(input()) for _ in range(5)]
# 위치를 찾기 쉽게 인덱스화
idx = [(i, j) for j in range(5) for i in range(5)]
cnt = 0
members = []
group(members, 0)
print(cnt)
결과
'[Algorithm] > 문제 풀이' 카테고리의 다른 글
[BOJ_Python]1913. 달팽이 (0) | 2024.10.17 |
---|---|
[BOJ_Python]1544. 사이클 단어 (2) | 2024.10.16 |
[BOJ]1600. 말이 되고픈 원숭이 (2) | 2024.10.10 |
[BOJ]9935. 문자열 폭발 (2) | 2024.09.23 |
[BOJ]1806. 부분합 (0) | 2024.09.09 |