728x90
백준 32825번 문제는 solved.ac기준 골드 4입니다.
python3말고 pypy3로 해야 시간 초과가 안납니다.
1. 문제 설명
이 문제는 5×5 크기의 격자판에 숫자를 배치하는 문제입니다. 변수 a부터 m까지 총 13개의 변수에 1부터 13까지의 숫자를 각각 한 번씩 할당해야 하며, 주어진 8개의 방정식을 만족해야 합니다.
방정식은 다음과 같습니다:
- A=a+e+i+l
- B=b+f+j+m
- C=c+g+k
- D=d+h
- E=a+b+c+d
- F=e+f+g+h
- G=i+j+k
- H=l+m
여기서 A부터 H까지는 주어진 정수입니다.
2. 문제 해결 방법
2.1 전체적인 전략
- 백트래킹(Backtracking)을 사용하여 모든 가능한 숫자 할당을 탐색합니다.
- 각 단계에서 현재까지의 할당이 방정식을 만족할 수 있는지 가지치기(Pruning)를 통해 확인하여 불필요한 탐색을 줄입니다.
- 할당된 숫자들은 1부터 13까지의 서로 다른 정수입니다.
2.2 구현 세부사항
- 변수와 방정식 설정
- 변수 목록: a부터 m까지 총 13개.
- 각 변수는 1부터 13까지의 숫자 중 하나를 할당받습니다.
- 변수의 인덱스는 편의를 위해 0부터 12까지로 설정합니다.
- 백트래킹 함수 작성
- 현재까지 할당된 변수들과 사용된 숫자 집합을 인자로 받는 재귀 함수를 작성합니다.
- 변수들을 순서대로 할당합니다.
- 각 단계에서 가능한 숫자들(아직 사용되지 않은 숫자들)에 대해 반복합니다.
- 가지치기 조건 설정
- 각 방정식을 미리 어느 변수들이 포함되어 있는지 매핑합니다.
- 변수를 할당할 때마다 해당 변수가 포함된 방정식의 현재 합과 필요한 합을 계산합니다.
- 현재 할당된 값들로부터 방정식을 만족할 가능성이 없으면 해당 경로를 더 이상 탐색하지 않습니다.
- 예를 들어, 방정식 A=a+e+i+l에서 a만 할당된 상태라면, 나머지 변수들 , i, l에 할당될 수 있는 최소값과 최대값을 계산하여 A를 만족할 수 있는지 확인합니다.
- 해결 방법의 효율성
- 가지치기를 통해 탐색 공간을 크게 줄일 수 있습니다.
- 백트래킹 알고리즘은 최대 약 13!개의 경우의 수를 가질 수 있지만, 가지치기를 통해 실제 탐색하는 경우의 수는 매우 작아집니다.
3. 백준 32825 숫자 할당 정답 파이썬 코드
import sys
# 입력 받기
A, B, C, D, E, F, G, H = map(int, sys.stdin.readline().split())
# 변수 인덱스 매핑
variables = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm']
# 방정식 매핑
equations = {
'A': {'vars': [0, 4, 8, 11], 'value': A},
'B': {'vars': [1, 5, 9, 12], 'value': B},
'C': {'vars': [2, 6, 10], 'value': C},
'D': {'vars': [3, 7], 'value': D},
'E': {'vars': [0, 1, 2, 3], 'value': E},
'F': {'vars': [4, 5, 6, 7], 'value': F},
'G': {'vars': [8, 9, 10], 'value': G},
'H': {'vars': [11, 12], 'value': H}
}
total_solutions = 0
used_numbers = [False] * 14 # 1부터 13까지 사용 여부
assigned_values = [0] * 13 # 각 변수에 할당된 값
def is_possible(eq_name):
eq = equations[eq_name]
current_sum = 0
unassigned_vars = []
for idx in eq['vars']:
if assigned_values[idx]:
current_sum += assigned_values[idx]
else:
unassigned_vars.append(idx)
min_possible = current_sum + len(unassigned_vars) * 1
max_possible = current_sum + len(unassigned_vars) * 13
return eq['value'] >= min_possible and eq['value'] <= max_possible
def check_constraints(var_idx):
# 변수 var_idx가 포함된 모든 방정식을 확인
var_equations = []
for eq_name, eq in equations.items():
if var_idx in eq['vars']:
var_equations.append(eq_name)
for eq_name in var_equations:
if not is_possible(eq_name):
return False
return True
def backtrack(idx):
global total_solutions
if idx == 13:
# 모든 변수가 할당되었을 때, 방정식 검증
for eq_name, eq in equations.items():
total = sum(assigned_values[i] for i in eq['vars'])
if total != eq['value']:
return
total_solutions += 1
return
else:
for num in range(1, 14):
if not used_numbers[num]:
assigned_values[idx] = num
used_numbers[num] = True
if check_constraints(idx):
backtrack(idx + 1)
assigned_values[idx] = 0
used_numbers[num] = False
# 초기 검증: E + F + G + H == 91인지 확인
if E + F + G + H != 91:
print(0)
else:
backtrack(0)
print(total_solutions)
4. 코드 설명
- 입력 처리
- 첫 줄에 A부터 H까지의 값을 입력받습니다.
- 변수 및 방정식 설정
- 변수들을 인덱스로 매핑하여 리스트로 관리합니다.
- 방정식들은 각 방정식마다 포함된 변수들의 인덱스와 필요한 합을 딕셔너리 형태로 저장합니다.
- 가지치기 함수
- is_possible(eq_name): 특정 방정식이 현재 상태에서 만족될 수 있는지 확인합니다.
- 현재까지 할당된 변수들의 합과 남은 변수들의 최소/최대 합을 계산하여 방정식의 값과 비교합니다.
- check_constraints(var_idx): 특정 변수에 값을 할당한 후, 그 변수가 포함된 모든 방정식을 검사합니다.
- is_possible(eq_name): 특정 방정식이 현재 상태에서 만족될 수 있는지 확인합니다.
- 백트래킹 함수
- backtrack(idx): 재귀적으로 변수를 할당하며 가능한 모든 경우를 탐색합니다.
- 모든 변수가 할당되면 방정식의 값을 정확히 만족하는지 확인하고, 만족하면 해결책 수를 증가시킵니다.
- 초기 검증
- 방정식 E+F+G+H=91인지 확인하여 아니면 바로 0을 출력합니다.
5. 백준 32825 제출 결과
도움이 되셨다면 공감과 댓글 부탁드립니다
728x90
'Python > 백준' 카테고리의 다른 글
백준 울려퍼져라 [32764] 파이썬(Python) 코드 + 해설 (2) | 2024.11.27 |
---|---|
백준 족보 검사하기 [32774] 파이썬(Python) 코드 + 해설 (1) | 2024.11.26 |
백준 마법사 상어와 파이어볼[20056] 파이썬(Python) 코드 + 해설 (1) | 2024.11.24 |
백준 자석 체스[32334] 파이썬(Python) 코드 + 해설 (0) | 2024.11.23 |
백준 하모니[32338] 파이썬(Python) 코드 + 해설 (0) | 2024.11.22 |