상세 컨텐츠

본문 제목

파이썬으로 풀어보는 백준 17471번: 게리맨더링 (삼성 A형 기출 문제)

Python/문제풀이 (삼성 A형 대비)

by 코딩하는 낙타 2020. 1. 23. 15:59

본문

https://www.acmicpc.net/problem/17471

 

17471번: 게리맨더링

선거구를 [1, 4], [2, 3, 5, 6]으로 나누면 각 선거구의 인구는 9, 8이 된다. 인구 차이는 1이고, 이 값보다 더 작은 값으로 선거구를 나눌 수는 없다.

www.acmicpc.net

 

내 풀이:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
= int(input())
people = list(map(int, input().split()))
people.insert(00)
connection = [[]]
answer = 10000
for _ in range(N):
    a = list(map(int, input().split()))
    del a[0]
    connection.append(a)
 
 
 
def making_team(index, A, B):
    global answer
    if index == N:
        if B == []:
            return
 
        for i in A:
            TF = False
            for j in A:
                if j in connection[i]:
                    TF = True
                    break
                else:
                    pass
            if not TF:
                return
 
        for i in B:
            TF = False
            for j in B:
                if j in connection[i]:
                    TF = True
                    break
                else:
                    pass
            if not TF:
                return
 
        sumA = 0
        sumB = 0
 
        for i in A:
            sumA += people[i]
        for i in B:
            sumB += people[i]
        result = abs(sumA - sumB)
 
        if answer > result:
            answer = result
 
        return
 
 
    A_new = A[:]
    B_new = B[:]
    A_new.append(index+1)
    B_new.append(index+1)
    making_team(index+1, A_new, B)
    making_team(index+1, A, B_new)
 
 
making_team(1, [1], [])
if answer == 10000:
    print("-1")
    exit()
print(answer)
 

Python3, 오답

샘플은 모두 통과하였으나 제출했을 때 오답 판정을 받았다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
= int(input())
people = list(map(int, input().split()))
people.insert(00)
connection = [[]]
answer = 1000
for _ in range(N):
    a = list(map(int, input().split()))
    del a[0]
    connection.append(a)
 
 
def checking(team):
    check_list = [team[0]]
    for _ in range(len(team)-1):
        for i in check_list:
            for j in connection[i]:
                if j not in check_list and j in team:
                    check_list.append(j)
    if len(check_list) == len(team):
        return True
    else:
        return False
 
 
def making_team(index, A, B):
    global answer
    if index == N:
        if B == []:
            return
 
        if not checking(A):
            return
 
        if not checking(B):
            return
 
        sumA = 0
        sumB = 0
 
        for i in A:
            sumA += people[i]
        for i in B:
            sumB += people[i]
        result = abs(sumA - sumB)
 
        if answer > result:
            answer = result
 
        return
 
    A_new = A[:]
    B_new = B[:]
    A_new.append(index+1)
    B_new.append(index+1)
    making_team(index+1, A_new, B)
    making_team(index+1, A, B_new)
 
 
making_team(1, [1], [])
if answer == 1000:
    print("-1")
    exit()
print(answer)
 

Python3, 80ms

선거구를 나누는 과정까진 오류가 없었으나 선거구를 정하고 그 선거구에 어느 한 구역도 빠짐없이 연결돼있는가를 확인하는 알고리즘이 틀렸었다. 처음 작성한 코드에서는 어느 구역이든 한 구역이라도 연결된 곳이 있다면 문제가 없다는 식으로 코딩을 했으나 4개의 구역으로 이루어진 선거구가 2/2로 쪼개진다면 조건을 만족하지 않음에도 조건을 통과하는 문제가 발생하기에 이를 수정하였다. 지금까지는 종이에 따로 문제에 대해 미리 적어보고 코딩을 시작하는 것이 아니라 문제를 읽는 즉시 코딩에 들어갔는데 이 때문에 문제 분석에 들어가는 시간이 배 이상으로 들어가는 것 같다. 시험 준비를 목표로 한다면 한 문제 한 문제 풀 때마다 미리 종이에 문제에 대한 조건 등을 분석하여 적어놓고 이를 토대로 코딩하는 연습이 필요할 것이다.

관련글 더보기

댓글 영역