본문 바로가기
백준알고리즘/백트래킹

(Python/🥇3)백준알고리즘 1941번: 소문난 칠공주

by windy7271 2024. 4. 20.
728x90
반응형

 

문제 바로가기 

소문난 칠공주

문제:

총 25명의 여학생들로 이루어진 여학생반은 5×5의 정사각형 격자 형태로 자리가 배치되었고, 얼마 지나지 않아 이다솜과 임도연이라는 두 학생이 두각을 나타내며 다른 학생들을 휘어잡기 시작했다. 곧 모든 여학생이 ‘이다솜파’와 ‘임도연파’의 두 파로 갈라지게 되었으며, 얼마 지나지 않아 ‘임도연파’가 세력을 확장시키며 ‘이다솜파’를 위협하기 시작했다. 위기의식을 느낀 ‘이다솜파’의 학생들은 과감히 현재의 체제를 포기하고, ‘소문난 칠공주’를 결성하는 것이 유일한 생존 수단임을 깨달았다. ‘소문난 칠공주’는 다음과 같은 규칙을 만족해야 한다. 이름이 이름인 만큼, 7명의 여학생들로 구성되어야 한다. 강한 결속력을 위해, 7명의 자리는 서로 가로나 세로로 반드시 인접해 있어야 한다. 화합과 번영을 위해, 반드시 ‘이다솜파’의 학생들로만 구성될 필요는 없다. 그러나 생존을 위해, ‘이다솜파’가 반드시 우위를 점해야 한다. 따라서 7명의 학생 중 ‘이다솜파’의 학생이 적어도 4명 이상은 반드시 포함되어 있어야 한다. 여학생반의 자리 배치도가 주어졌을 때, ‘소문난 칠공주’를 결성할 수 있는 모든 경우의 수를 구하는 프로그램을 작성하시오.

입력:

'S'(이다‘솜’파의 학생을 나타냄) 또는 'Y'(임도‘연’파의 학생을 나타냄)을 값으로 갖는 5*5 행렬이 공백 없이 첫째 줄부터 다섯 줄에 걸쳐 주어진다.

출력:

첫째 줄에 ‘소문난 칠공주’를 결성할 수 있는 모든 경우의 수를 출력한다.

 

첫풀이:

import sys
from collections import defaultdict, deque

sys.stdin = open('/Users/song/Desktop/Python/Python/h.txt', 'r')

graph = [list(map(str, sys.stdin.readline().rstrip())) for _ in range(5)]
print(graph)
move = [(0, 1), (0, -1), (1, 0), (-1, 0)]

# s : 4이상,
dic = defaultdict(int)
count = 0


def bt(x, y, visited, depth):
    global count
    if depth == 6 and dic["S"] >= 4:
            count += 1
    if not visited[x][y]:
        visited[x][y] = True
        for dx, dy in move:
            nx = x + dx
            ny = y + dy
            if 0 <= nx < 5 and 0 <= ny < 5:
                dic[graph[nx][ny]] += 1
                bt(nx, ny, visited, depth + 1)
                dic[graph[nx][ny]] -= 1
for x in range(5):
    for y in range(5):
        visited = [[False] * 5 for _ in range(5)]
        dic[graph[x][y]] += 1
        bt(x, y, visited, 0)
        dic[graph[x][y]] -= 1
print(count)

 

생각해보니 중복으로 잡혀 5개가 나온다.. 뭔가 잘 못 되었다..... 오랜만에 bt라 마음대로 되지 않는다...

방식을 바꿔보려고한다.

 

5*5 중에 7개 좌표를 일단 뽑아보고 칠공주인지 확인후 그것들이 연결되어있는지 확인하는 방식으로 가져가려고 한다.

 

import sys
from collections import deque
from itertools import combinations

sys.stdin = open('/Users/song/Desktop/Python/Python/h.txt', 'r')

graph = [list(map(str, sys.stdin.readline().rstrip())) for _ in range(5)]
move = [(-1, 0), (1, 0), (0, -1), (0, 1)]
positions = [(i, j) for i in range(5) for j in range(5)]
combis = list(combinations(positions, 7))
count = 0


def checkS(combi):
    return sum(1 for x, y in combi if graph[x][y] == "S") >= 4


# 다 연결되어있는지 확인
def checkBFS(combi):
    visited = [False] * 7
    Q = deque([(combi[0])])
    visited[0] = True

    while Q:
        x, y = Q.popleft()
        for dx, dy in move:
            nx = dx + x
            ny = dy + y
            if (nx, ny) in combi and not visited[combi.index((nx, ny))]:
                visited[combi.index((nx, ny))] = True
                Q.append((nx, ny))
    return False if False in visited else True
res = 0
for combi in combis:
    if checkS(combi):
        if checkBFS(combi):
            res += 1

print(res)

 

요렇게 푼다. 파이썬이라 살렸다.

 

https://www.youtube.com/watch?v=DWdFSOehwFI

여기 강의도 있던데 

일자로 펼쳐서한다 연결되어있는지 확인하려고 그런것 같다

반응형

댓글