[Gold III] Title: 소문난 칠공주, Time: 1360 ms, Memory: 34992 KB -BaekjoonHub

This commit is contained in:
SSUM
2026-02-09 20:52:24 +09:00
parent a9ce5948b0
commit 98ec7c18a9
2 changed files with 103 additions and 0 deletions

View File

@@ -0,0 +1,39 @@
# [Gold III] 소문난 칠공주 - 1941
[문제 링크](https://www.acmicpc.net/problem/1941)
### 성능 요약
메모리: 34992 KB, 시간: 1360 ms
### 분류
수학, 그래프 이론, 브루트포스 알고리즘, 그래프 탐색, 조합론, 너비 우선 탐색, 백트래킹
### 제출 일자
2026년 2월 9일 20:52:15
### 문제 설명
<p>총 25명의 여학생들로 이루어진 여학생반은 5×5의 정사각형 격자 형태로 자리가 배치되었고, 얼마 지나지 않아 이다솜과 임도연이라는 두 학생이 두각을 나타내며 다른 학생들을 휘어잡기 시작했다. 곧 모든 여학생이 ‘이다솜파’와 ‘임도연파’의 두 파로 갈라지게 되었으며, 얼마 지나지 않아 ‘임도연파’가 세력을 확장시키며 ‘이다솜파’를 위협하기 시작했다.</p>
<p>위기의식을 느낀 ‘이다솜파’의 학생들은 과감히 현재의 체제를 포기하고, ‘소문난 칠공주’를 결성하는 것이 유일한 생존 수단임을 깨달았다. ‘소문난 칠공주’는 다음과 같은 규칙을 만족해야 한다.</p>
<ol>
<li>이름이 이름인 만큼, 7명의 여학생들로 구성되어야 한다.</li>
<li>강한 결속력을 위해, 7명의 자리는 서로 가로나 세로로 반드시 인접해 있어야 한다.</li>
<li>화합과 번영을 위해, 반드시 ‘이다솜파’의 학생들로만 구성될 필요는 없다.</li>
<li>그러나 생존을 위해, ‘이다솜파’가 반드시 우위를 점해야 한다. 따라서 7명의 학생 중 ‘이다솜파’의 학생이 적어도 4명 이상은 반드시 포함되어 있어야 한다.</li>
</ol>
<p>여학생반의 자리 배치도가 주어졌을 때, ‘소문난 칠공주’를 결성할 수 있는 모든 경우의 수를 구하는 프로그램을 작성하시오.</p>
### 입력
<p>'S'(이다‘솜’파의 학생을 나타냄) 또는 'Y'(임도‘연’파의 학생을 나타냄)을 값으로 갖는 5*5 행렬이 공백 없이 첫째 줄부터 다섯 줄에 걸쳐 주어진다.</p>
### 출력
<p>첫째 줄에 ‘소문난 칠공주’를 결성할 수 있는 모든 경우의 수를 출력한다.</p>

View File

@@ -0,0 +1,64 @@
from collections import deque
# bfs로 7명의 여학생이 붙어있는지 확인한다.
def bfs(arr):
dr = [-1, +1, 0, 0] # 상하좌우
dc = [0, 0, -1, +1] # 상하좌우
# 7명 여학생 위치 방문처리를 위한 리스트 1로 처리
visited = [[1] * 5 for _ in range(5)]
# 7명의 여학생 위치를 0으로 초기화
for i in arr:
visited[i[0]][i[1]] = 0
# 첫번째 여학생의 위치를 큐에 넣는다.
queue = deque([(arr[0])])
# 첫번째 여학생의 방문처리를 1로 변경
visited[arr[0][0]][arr[0][1]] = 1
check = 1 # 여학생들의 위치 방문 횟수(첫 위치 방문했기 때문에 1)
while queue:
r, c = queue.popleft() # 큐에 있는 위치 꺼내기
for i in range(4): # 델타 위치를 이동하면서
nr = r + dr[i]
nc = c + dc[i]
# 범위를 벗어나면 진행x
if nr < 0 or nr >= 5 or nc < 0 or nc >= 5:
continue
# 만약 위치를 이동하다 아직 여학생 위치를 방문안했다면
if not visited[nr][nc]:
visited[nr][nc] = 1 # 그위치를 1로 바꿔주고
check += 1 # 방문 횟수를 1 증가
queue.append((nr, nc)) # 큐에 추가
if check != 7: # 7번다 방문하지 않았다면
return False
else: # 7번 방문했다면
return True
def dfs(depth, start, count):
global result
if count >= 4: # 만약 임도연파가 4명이상이라면
return # 재귀 탈출
if depth == 7: # 7명을 뽑았다면
if bfs(arr): # 모든 여학생들이 붙어있다면
result += 1 # 횟수 1번 추가
return
for i in range(start, 25):
r = i // 5 # 총 25번 중 행은 i 나누기 5와 같다.
c = i % 5 # 총 25번 중 열은 i를 5로 나눈 나머지와 같다.
arr.append((r, c)) # 해당 위치를 추가
dfs(depth + 1, i + 1, count + (students[r][c] == 'Y')) # 재귀 돈다.
arr.pop() # 해당 위치를 제거
students = [list(input()) for _ in range(5)]
arr = []
result = 0
dfs(0, 0, 0)
print(result)