Algorithm/acmicpc.net

스타트와 링크 링크와 스타트

winney916 2022. 1. 19. 19:04
728x90

#14889번 스타트와 링크 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

import sys
N = int(input())
matrix = []

for i in range(N):
    matrix.append(list(map(int, sys.stdin.readline().split())))


def get_sum(team):
    parts = 0
    for i in range(len(team)):
        for j in range(i+1, len(team)):
            parts += (matrix[team[i]][team[j]] + matrix[team[j]][team[i]])
    return parts


members = []
answer = 100


def solve(depth, prev):
    global answer
    if depth == N//2:
        second_team = [x for x in range(N) if x not in members]
        tmp = abs(get_sum(members) - get_sum(second_team))
        answer = min(answer, tmp)
        return

    for i in range(prev, N):
        members.append(i)
        solve(depth+1, i+1)
        members.pop()


solve(0, 0)
print(answer)

뭐 재귀를 통해 무난하게 해결

 

다음에 바로 유사한 문제를 만났다.

 

#15661번 링크와 스타트https://www.acmicpc.net/problem/15661

 

15661번: 링크와 스타트

첫째 줄에 N(4 ≤ N ≤ 20)이 주어진다. 둘째 줄부터 N개의 줄에 S가 주어진다. 각 줄은 N개의 수로 이루어져 있고, i번 줄의 j번째 수는 Sij 이다. Sii는 항상 0이고, 나머지 Sij는 1보다 크거나 같고, 100

www.acmicpc.net

차이점은 인원수가 동일하지 않을 때도 계산해야한다는 점.

 

나는 기존의 코드를 재사용하려고 했다.

import sys
N = int(input())
matrix = []

for i in range(N):
    matrix.append(list(map(int, sys.stdin.readline().split())))


def get_sum(team):
    parts = 0
    for i in range(len(team)):
        for j in range(i+1, len(team)):
            parts += (matrix[team[i]][team[j]] + matrix[team[j]][team[i]])
    return parts


visited = [False]*N
answer = 1000


def solve(depth, prev, stop):
    global answer
    if depth == stop:
        members, second_team = [], []
        for i in range(N):
            if visited[i]:
                members.append(i)
            else:
                second_team.append(i)
        if len(members) * len(second_team) == 0:
            return
        answer = min(answer, abs(get_sum(members) - get_sum(second_team)))
        return

    for i in range(prev, N):
        visited[i] = True
        solve(depth+1, i+1, stop)
        visited[i] = False


for i in range(1, N//2+1):
    solve(0, 0, i)

print(answer)

기존의 종료조건을 1~절반까지 가변하는 방식으로 구현했다.

 

그런데 결과는 시간초과. 결국 pypy3로 통과했다.

 

아예 다른 방법이 필요하다.

 

import sys
from itertools import combinations

input = sys.stdin.readline

n = int(input())

matrix = [list(map(int,input().split())) for _ in range(n)]

d = 20*100
for i in combinations(range(n),n//2):

    s_team = [*i]
    l_team = list(set(range(n)) - set(s_team))

    s_score = 0
    l_score = 0
    for j in combinations(s_team,2):
        s_score += matrix[j[0]][j[1]] + matrix[j[1]][j[0]]
    
    for j in combinations(l_team,2):
        l_score += matrix[j[0]][j[1]] + matrix[j[1]][j[0]]
    
    sub = abs(s_score - l_score)

    if sub == 0:
        d = sub
        break

    elif d > sub:
        d = sub

print(d)

근데 뭐 역시나 itertools 라이브러리를 사용한 방법밖에 찾지 못했다.

 

파이썬을 파이썬답게 쓰는 방법은 라이브러리를 꼭 사용해야하는걸까?

뭐 앞으로 코딩테스트를 진행할 언어를 바꿀 생각은 없지만

파이썬은 항상 기본 라이브러리를 활용할 때 가장 빠른걸까

 

여러 의문의 드는 하루였다.

'Algorithm > acmicpc.net' 카테고리의 다른 글

비트마스크  (0) 2022.01.21
골드의 길은 멀고도 험하다  (0) 2022.01.20
악 DP!!  (0) 2022.01.19
다음수열, 이전수열  (0) 2022.01.13
백트래킹 : M과 N, 순열  (0) 2022.01.11