728x90
시간 제한 2초, 메모리 제한 512MB
# 조건
- 오늘은 스타트링크에 다니는 사람들이 모여서 축구를 해보려고 한다.
- 축구는 평일 오후에 하고 의무 참석도 아니다.
- 축구를 하기 위해 모인 사람은 총 N명이고 신기하게도 N은 짝수이다.
- 이제 N/2명으로 이루어진 스타트 팀과 링크 팀으로 사람들을 나눠야 한다.
- BOJ를 운영하는 회사 답게 사람에게 번호를 1부터 N까지로 배정했고, 아래와 같은 능력치를 조사했다.
- 능력치 Sij는 i번 사람과 j번 사람이 같은 팀에 속했을 때, 팀에 더해지는 능력치이다.
- 팀의 능력치는 팀에 속한 모든 쌍의 능력치 Sij의 합이다.
- Sij는 Sji와 다를 수도 있으며, i번 사람과 j번 사람이 같은 팀에 속했을 때, 팀에 더해지는 능력치는 Sij와 Sji이다.
- N=4이고, S가 아래와 같은 경우를 살펴보자.
- 예를 들어, 1, 2번이 스타트 팀, 3, 4번이 링크 팀에 속한 경우에 두 팀의 능력치는 아래와 같다.
- 스타트 팀: S12 + S21 = 1 + 4 = 5
- 링크 팀: S34 + S43 = 2 + 5 = 7
- 1, 3번이 스타트 팀, 2, 4번이 링크 팀에 속하면, 두 팀의 능력치는 아래와 같다.
- 스타트 팀: S13 + S31 = 2 + 7 = 9
- 링크 팀: S24 + S42 = 6 + 4 = 10
- 축구를 재미있게 하기 위해서 스타트 팀의 능력치와 링크 팀의 능력치의 차이를 최소로 하려고 한다.
- 위의 예제와 같은 경우에는 1, 4번이 스타트 팀, 2, 3번 팀이 링크 팀에 속하면 스타트 팀의 능력치는 6, 링크 팀의 능력치는 6이 되어서 차이가 0이 되고 이 값이 최소이다.
입력
- 첫째 줄에 N(4 ≤ N ≤ 20, N은 짝수)이 주어진다.
- 둘째 줄부터 N개의 줄에 S가 주어진다. 각 줄은 N개의 수로 이루어져 있고, i번 줄의 j번째 수는 Sij 이다.
- Sii는 항상 0이고, 나머지 Sij는 1보다 크거나 같고, 100보다 작거나 같은 정수이다.
출력
- 첫째 줄에 스타트 팀과 링크 팀의 능력치의 차이의 최솟값을 출력한다.
# 접근 방법
- DFS와 백트래킹을 이용하여 풀어주면 된다.
- 주어진 입력을 받고 DFS 함수에 현재 인원수와, 번호를 넣어준다.
- 만약 현재가 절반의 인원을 한 쪽 팀에 구성했다면 => depth == n//2
- 2중 반복문을 통해 visted 배열을 순회해준다.
- 만약 i와 j가 같은 팀이라면 graph[i][j] 를 더해준다.
- 둘 다 방문하지 않았다면 => 상대팀이라면 power2 에 더해준다.
- 모든 시너지를 더한 후 갱신해주면 된다.
- 이 때 백트래킹을 활용하여 현재 인원의 재귀가 끝난 뒤 다시 False로 방문 배열을 변경해주어야 모든 조합을 구할 수 있다.
- 또는 조합을 이용하여 절반만큼의 인원을 구성한 뒤, 제일 앞과 제일 뒤에서부터 start와 link팀을 각각 구성하며 구해줄 수도 있다.
def dfs(depth, idx):
global min_diff
if depth == n//2:
power1, power2 = 0, 0
for i in range(n):
for j in range(n):
if visited[i] and visited[j]:
power1 += graph[i][j]
elif not visited[i] and not visited[j]:
power2 += graph[i][j]
min_diff = min(min_diff, abs(power1-power2))
return
for i in range(idx, n):
if not visited[i]:
visited[i] = True
dfs(depth+1, i+1)
visited[i] = False
n = int(input())
visited = [False for _ in range(n)]
graph = [list(map(int, input().split())) for _ in range(n)]
min_diff = int(1e9)
dfs(0, 0)
print(min_diff)
728x90
'ALGORITHM > 백트래킹' 카테고리의 다른 글
[백준 15684번] 파이썬 - 사다리 조작 (0) | 2023.10.12 |
---|---|
[백준 6987번] 파이썬 - 월드컵 (0) | 2023.09.12 |
[백준 1342번] 파이썬 - 행운의 문자열 (0) | 2023.08.30 |
[백준 3980번] 파이썬 - 선발 명단 (0) | 2023.08.27 |
[백준 28447번] 파이썬 - 마라탕 재료 고르기 (0) | 2023.08.16 |