728x90

백준 14889번: 스타트와 링크
📌 문제
오늘은 스타트링크에 다니는 사람들이 모여서 축구를 해보려고 한다. 축구는 평일 오후에 하고 의무 참석도 아니다. 축구를 하기 위해 모인 사람은 총 N명이고 신기하게도 N은 짝수이다. 이제 N/2명으로 이루어진 스타트 팀과 링크 팀으로 사람들을 나눠야 한다.
BOJ를 운영하는 회사 답게 사람에게 번호를 1부터 N까지로 배정했고, 아래와 같은 능력치를 조사했다. 능력치 는 i번 사람과 j번 사람이 같은 팀에 속했을 때, 팀에 더해지는 능력치이다. 팀의 능력치는 팀에 속한 모든 쌍의 능력치 Sij의 합이다. 는 와 다를 수도 있으며, i번 사람과 j번 사람이 같은 팀에 속했을 때, 팀에 더해지는 능력치는 와 이다.
N=4이고, S가 아래와 같은 경우를 살펴보자.
예를 들어, 1, 2번이 스타트 팀, 3, 4번이 링크 팀에 속한 경우에 두 팀의 능력치는 아래와 같다.
스타트 팀: + = 1 + 4 = 5
링크 팀: + = 2 + 5 = 7
1, 3번이 스타트 팀, 2, 4번이 링크 팀에 속하면, 두 팀의 능력치는 아래와 같다.
스타트 팀: + = 2 + 7 = 9
링크 팀: + = 6 + 4 = 10
축구를 재미있게 하기 위해서 스타트 팀의 능력치와 링크 팀의 능력치의 차이를 최소로 하려고 한다. 위의 예제와 같은 경우에는 1, 4번이 스타트 팀, 2, 3번 팀이 링크 팀에 속하면 스타트 팀의 능력치는 6, 링크 팀의 능력치는 6이 되어서 차이가 0이 되고 이 값이 최소이다.
입력
첫째 줄에 N(4 ≤ N ≤ 20, N은 짝수)이 주어진다. 둘째 줄부터 N개의 줄에 S가 주어진다. 각 줄은 N개의 수로 이루어져 있고, i번 줄의 j번째 수는 이다. 는 항상 0이고, 나머지 는 1보다 크거나 같고, 100보다 작거나 같은 정수이다.
출력
첫째 줄에 스타트 팀과 링크 팀의 능력치의 차이의 최솟값을 출력한다.
📝 문제 분석
이 문제에서는 축구를 하기 위해 모인 N
명의 사람들을 N/2
명씩 두 팀(스타트 팀과 링크 팀)으로 나누어야 합니다. 각 사람이 다른 사람과 함께 팀을 이뤘을 때의 능력치가 S[i][j]
라는 표로 주어집니다.
🎯 문제의 목표
N
명의 사람을 두 팀으로 나누는 모든 경우의 수를 고려해야 합니다.- 각 팀의 능력치를 계산해야 합니다.
- 두 팀의 능력치 차이가 최소가 되도록 해야 합니다.
🔍 예제 분석
입력 예제 1
4
0 1 2 3
4 0 5 6
7 1 0 2
3 4 5 0
- 예를 들어, 1번 사람과 2번 사람이 같은 팀이라면 능력치는 S[1][2] + S[2][1] = 1 + 4 = 5가 됩니다.
1️⃣ 팀 조합 1
- 스타트 팀: [1, 2] → S[1][2] + S[2][1] = 1 + 4 = 5
- 링크 팀: [3, 4] → S[3][4] + S[4][3] = 2 + 5 = 7
- 차이: |5 - 7| = 2
2️⃣ 팀 조합 2
- 스타트 팀: [1, 3] → S[1][3] + S[3][1] = 2 + 7 = 9
- 링크 팀: [2, 4] → S[2][4] + S[4][2] = 6 + 4 = 10
- 차이: |9 - 10| = 1
3️⃣ 팀 조합 3
- 스타트 팀: [1, 4] → S[1][4] + S[4][1] = 3 + 3 = 6
- 링크 팀: [2, 3] → S[2][3] + S[3][2] = 5 + 1 = 6
- 차이: |6 - 6| = 0 ✅ 최적의 팀 조합!
💡 아이디어
1️⃣ Step 1: 팀을 나누는 모든 경우의 수를 찾기
📌 목표
- N명의 사람을 두 개의 팀(스타트 팀과 링크 팀)으로 나누는 방법을 찾습니다.
- 각 팀의 인원 수는
N/2
명이 되어야 합니다. - 가능한 모든 팀 조합을 고려해야 하며 완전 탐색을 통해 해결 가능합니다.
📌 예제: N = 4
스타트 팀: [1, 2] | 링크 팀: [3, 4]
스타트 팀: [1, 3] | 링크 팀: [2, 4]
스타트 팀: [1, 4] | 링크 팀: [2, 3]
이처럼 가능한 모든 조합을 고려해야 합니다.
✅ 해결 방법: 비트마스크 활용
for mask in range(1 << n): # 0부터 2^N - 1까지 반복
if bin(mask).count('1') == n // 2: # N/2명을 선택한 경우만 고려
start_team = []
link_team = []
for i in range(n):
if mask & (1 << i): # i번째 비트가 1이면 스타트 팀
start_team.append(i)
else: # i번째 비트가 0이면 링크 팀
link_team.append(i)
1 << n
은2^N
을 의미하며0
부터2^N - 1
까지 모든 경우의 수를 탐색합니다.- 예를 들어, N=4이면 0~15(0000~1111)까지 모든 경우의 수를 탐색합니다.
bin(mask).count('1') == n // 2
조건을 사용하여 정확히N/2
명을 선택한 경우만 선택합니다.bin(mask).count('1')
은 이진수에서 1의 개수(스타트 팀의 크기)를 반환합니다.
- 비트 연산(
&
)을 이용해 스타트 팀과 링크 팀을 구분합니다.1 << i
는i
번째 비트를 1로 만드는 연산입니다.mask & (1 << i)
는i
번째 비트가 1인지 확인하는 연산입니다.
2️⃣ Step 2: 각 팀의 능력치를 계산하기
📌 목표
- 한 팀에 속한 모든
(i, j)
조합을 찾아 능력치를 합산합니다.
✅ 해결 방법
def cal_sum(team, s):
sum_value = 0
for i in range(len(team)):
for j in range(i+1, len(team)): # i와 j의 모든 쌍을 고려
p1, p2 = team[i], team[j]
sum_value += s[p1][p2] + s[p2][p1] # 팀 능력치 합산
return sum_value
# 각 팀의 능력치 계산
start_ability = cal_sum(start_team, s)
link_ability = cal_sum(link_team, s)
team
리스트에서 모든(i, j)
쌍을 찾아 능력치S[i][j] + S[j][i]
를 합산합니다.
3️⃣ Step 3: 능력치 차이의 최솟값 찾기
📌 목표
- 두 팀의 능력치 차이를 최소화해야 합니다.
✅ 해결 방법
import sys
min_diff = sys.maxsize # 매우 큰 값으로 초기화
# 최소 차이 갱신
min_diff = min(min_diff, abs(start_ability - link_ability))
sys.maxsize
를 사용하여 초기값을 큰 값으로 설정합니다.- 가능한 모든 팀 조합에 대해 스타트 팀과 링크 팀의 능력치를 계산한 후 두 팀의 능력치 차이를 갱신합니다.
👩💻 나의 답안
import sys
def cal_sum(team):
sum_value = 0
for i in range(len(team)):
for j in range(i+1, len(team)):
p1, p2 = team[i], team[j]
sum_value += s[p1][p2] + s[p2][p1]
return sum_value
n = int(input())
s = [list(map(int, input().split())) for _ in range(n)]
min_diff = sys.maxsize
for mask in range(1 << n):
if bin(mask).count('1') == n//2:
start_team = []
link_team = []
for i in range(n):
if mask & (1 << i):
start_team.append(i)
else:
link_team.append(i)
start_ability = cal_sum(start_team)
link_ability = cal_sum(link_team)
min_diff = min(min_diff, abs(start_ability - link_ability))
print(min_diff)
Algorithm/백준/Silver/14889. 스타트와 링크 at main · kuun1000/Algorithm
This is a auto push repository for Baekjoon Online Judge created with [BaekjoonHub](https://github.com/BaekjoonHub/BaekjoonHub). - kuun1000/Algorithm
github.com
728x90
'코딩테스트 대비' 카테고리의 다른 글
[파이썬(Python)] 백준 13023번 ABCDE - 그래프 (0) | 2025.02.27 |
---|---|
[파이썬(Python)] 백준 14391번 종이 조각 - 비트마스크 (0) | 2025.02.26 |
[파이썬(Python)] 백준 1182번 부분수열의 합 (0) | 2025.02.24 |
[파이썬(Python)] 백준 11723번 집합 (0) | 2025.02.21 |
[파이썬(Python)] 백준 14889번 스타트와 링크 (0) | 2025.02.19 |