문제 링크
https://www.acmicpc.net/problem/14889
14889번: 스타트와 링크
예제 2의 경우에 (1, 3, 6), (2, 4, 5)로 팀을 나누면 되고, 예제 3의 경우에는 (1, 2, 4, 5), (3, 6, 7, 8)로 팀을 나누면 된다.
www.acmicpc.net
풀이
백트래킹 문제라고 생각하여, dfs로 풀어보았다. -> 그러나 시간초과
dfs 변수로 선택한 사람의 수와 선택한 사람 번호가 담긴 set을 전달하는데,
선택한 사람의 수가 n//2 이면 점수차이를 계산해주었다.
# 시간 초과 코드
n = int(input())
graph = []
for _ in range(n):
graph.append(list(map(int,input().split())))
def cal(s):
num1 = 0
num2 = 0
for i in range(n):
for j in range(n):
# 같은 팀이면
if i in s and j in s:
num1 += graph[i][j]
if i not in s and j not in s:
num2 += graph[i][j]
return abs(num1-num2)
visited = [False] * n
ans = int(1e9)
def dfs(cnt, s):
global ans
# n//2 명 뽑았으면 점수차이 계산
if cnt == n//2 :
result = cal(s)
ans = min(ans, result)
return
# 백트래킹
for i in range(n):
if visited[i]:
continue
visited[i] = True
s.add(i)
dfs(cnt+1, s)
s.remove(i)
visited[i]=False
dfs(0,set())
print(ans)
이게.. 1,2,3,4 번의 사람이 있다고 했을 때 (1,2)가 선택된 경우와 (3,4)가 선택된 경우는 결과적으로 같은 경우인데 또 계산해서 그런 것 같다... 조합으로 풀어보았다.
조합도 combinations 라이브러리를 사용하지 않고, 함수로 구현했다. 통과 !
# 조합 구하기
def comb(arr, n):
result = []
if n > len(arr):
return result
if n == 1:
for i in range(len(arr)):
result.append([arr[i]])
elif n> 1 :
for i in range(len(arr)-n+1):
for j in comb(arr[i+1:], n-1):
result.append([arr[i]]+j)
return result
# 점수 구하기
def cal(s):
num = 0
for i in s :
for j in s :
if i == j:
continue
num += graph[i][j]
return num
n = int(input())
graph = []
for _ in range(n):
graph.append(list(map(int,input().split())))
arr = [ i for i in range(n)]
# n//2개만 구하면 된다. 속하지 않은 사람이 나머지 팀
combine = comb(arr, n//2)
ans = int(1e9)
for c in combine:
tmp = [ i for i in range(n)]
# 상대팀구하기
for i in c:
tmp.remove(i)
num1 = cal(c)
num2 = cal(tmp)
ans = min(ans, abs(num1-num2))
print(ans)
'개발 > algorithm' 카테고리의 다른 글
[백준 15684번] 사다리 조작 - python (0) | 2022.10.07 |
---|---|
[백준 14890번] 경사로 - Python (1) | 2022.10.07 |
[백준 23288번] 주사위 굴리기2 - python (0) | 2022.10.06 |
[백준 21611번] 마법사 상어와 블리자드 - python (1) | 2022.10.06 |
[백준 21609번] 상어 중학교 - python (0) | 2022.10.06 |