본문으로 바로가기

SW Expert Academy [2차원 배열 탐색 연습문제] 4615. 재미있는 오셀로 게임

문제에서는 오셀로라는 게임의 규칙에 따라 흑,백의 돌을 놓고

플레이어가 돌을 모두 두었을 때, 게임판에 올려진 흑,백의 돌의 개수를 각각 출력해야 한다.

이 문제는 백준 15671. 오델로와 유사한 문제기 때문에, 이 문제를 푼다면 백준의 문제도 풀 수가 있다.

만약 SW Expert Academy 4615. 재미있는 오셀로 게임을 푸는데 테스트 케이스를 모두 통과하지 못한다면

게임판을 6*6 크기로 한정한 백준의 오델로 문제를 먼저 풀어보자.

삼성 SW Expert Academy에서 푼 문제 리스트 보기

백준 15671. 오델로 풀이 보러 가기

github에서 코드 보기

문제에서 제시한 조건

자신이 놓을 돌과 자신의 돌 사이에 상대편의 돌이 있을 경우에만 그 곳에 돌을 놓을 수 있다.

테스트 케이스를 통과하지 못했다면 확인할 사항

돌과 돌 사이에 상대방의 돌이 있다는 것은 그 사이에 빈칸이 존재해서는 안된다는 의미이다. 

(0,0)에 흑돌(2)을 놓는 경우에 빨간색 1(1,0)과 파란색 1(1,1) 중에서 파란색 1(1,1)만 값이 변경된다. (2,0)에 빈칸이 있기 때문에 변경 될 수 없다.

<초기 모습> 1의 갯수 : 6 , 2의 갯수 : 2

arr = [  

    [(2),  1,  1, 0],

    [  1 1,  1, 0],

    [ 0, 1, 2, 0],

    [ 2, 0, 0, 0],

]

<변경된 모습> 1의 갯수 : 5 , 2의 갯수 : 4

arr = [  

    [ 2,  1,  1, 0],

    [ 1,  2,  1, 0],

    [0,  1,  2, 0],

    [ 2, 0, 0, 0],

]


풀이

나는 기존에 놓여 있던 돌들의 위치와 새로운 돌의 위치를 비교해서 같은 행에 위치, 같은 열에 위치, 대각선상에 위치 하는지를 먼저 파악했다.

기존 돌 (pos_r, pos_c), 새로운 돌(r, c)이라고 한다면,
기존 돌과 새로운 돌이 같은 행에 위치 : pos_r과 r이 같다.
기존 돌과 새로운 돌이 같은 열에 위치 : pos_c와 c가 같다.
기존 돌과 새로운 돌이 대각선상에 위치 : 절대값 (pos_r - r) == 절대값 (pos_c - c)이 일치

기존 돌과 새로운 돌이 같은 행, 같은 열, 대각선상에 위치할 경우에 상대의 돌을 뒤집어 주었다.
다만, 문제를 풀다보면 위에 정리해둔 '테스트 케이스를 통과하지 못했다면 확인할 사항'에서의 상황은 어떻게 처리해야 하는지 의문이 들 수 있다. 
두 돌이 상대의 돌을 감쌀 때, 상대의 돌을 뒤집으려면 반드시 빈 공간 없이 양 끝을 직접 막아야 한다. 이 조건을 기억하고 문제를 풀면 쉽게 풀 수 있다.

파이썬 코드

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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
"""
SW Expert Academy 4615. 재미있는 오셀로 게임
blog : https://daimhada.tistory.com/59
"""
 
def changeArr(arr, color_list, pos, color, n):
    r, c = pos
    changed = set()
    changed.add((r, c))
    for po in color_list:
        pr, pc = po[0], po[1]
        temp = set() # 변경 예정인 돌들을 넣는다.
        # 가로, 세로, 대각선인지 체크
        # 기존 돌(po)이 새로 놓을 돌의 위치로 이동하듯 상대돌이 있는지 체크
        if pr == r:
            count = abs(pc - c) - 1
            # 같은 가로줄에 위치, pc가 c가 되도록 수를 1만큼 더하거나 빼준다
            while count:
                count -= 1
                if pc > c:
                    pc -= 1
                else:
                    pc += 1
                # 내 색의 돌이 나올 경우 뒤집기 취소
                if arr[r][pc] == color:
                    temp = set()
                    break
                # 빈 칸이 나올 경우 뒤집기 취소
                if arr[r][pc] == '.':
                    temp = set()
                    break
                # 변경할 임시 돌들을 저장함
                temp.add((r, pc))
            changed.update(temp) # 변경할 돌 리스트에 추가
        elif pc == c:
            count = abs(pr - r) - 1
            # 같은 세로줄에 위치, pr이 r이 되도록 수를 1만큼 더하거나 빼준다.
            while count:
                count -= 1
                if pr > r:
                    pr -= 1
                else:
                    pr += 1
 
                if arr[pr][c] == color:
                    temp = set()
                    break
 
                if arr[pr][c] == '.':
                    temp = set()
                    break
                temp.add((pr,c))
            changed.update(temp)
        elif abs(pr - r) == abs(pc - c) and abs(pc - c) > 1:
            # 돌이 대각선상에 위치
            # 기존 돌(po)이 새로운 돌이 있는 곳까지 대각선으로 한칸씩 이동한다.
            count = abs(pr - r) - 1 # 최대 count만큼 반복하면 된다.
 
            if pr > r:
                # 기존 돌(po)이 새로운 돌(r,c)보다 아래에 위치 (pr 감소)
                if pc > c:
                    # 기존 돌(po)가 새로운 돌(r,c)보다 오른쪽에 위치 (pc 감소)
                    while count:
                        pr -= 1
                        pc -= 1
                        count -= 1
                        if arr[pr][pc] == color:
                            temp = set()
                            break
                        if arr[pr][pc] == '.':
                            temp = set()
                            break
                        temp.add((pr, pc))
                    changed.update(temp)
                else:
                    # 기존 돌(po)가 새로운 돌(r,c)보다 왼쪽에 위치 (pc 증가)
                    while count:
                        pr -= 1
                        pc += 1
                        count -= 1
                        if arr[pr][pc] == color:
                            temp = set()
                            break
                        if arr[pr][pc] == '.':
                            temp = set()
                            break
                        temp.add((pr, pc))
                    changed.update(temp)
            else:
                # 기존 돌(po)이 새로운 돌(r,c)보다 위에 위치 (pr 증가)
                if pc > c:
                    # 기존 돌(po)이 새로운 돌보다 오른쪽에 위치 (pc 감소)
                    while count:
                        pr += 1
                        pc -= 1
                        count -= 1
                        if arr[pr][pc] == color:
                            temp = set()
                            break
                        if arr[pr][pc] == '.':
                            temp = set()
                            break
                        temp.add((pr, pc))
                    changed.update(temp)
                else:
                    # 기존 돌(po)이 새로운 돌보다 왼쪽에 위치 (pc 증가)
                    while count:
                        pr += 1
                        pc += 1
                        count -= 1
                        if arr[pr][pc] == color:
                            temp = set()
                            break
                        if arr[pr][pc] == '.':
                            temp = set()
                            break
                        temp.add((pr,pc))
                    changed.update(temp)
    return changed
 
def solve(posList, arr, n):
    black_list = set()
    white_list = set()
    # setting
    r = (n//2- 1
    white_list.update([(r,r),(r+1, r+1)])
    black_list.update([(r+1,r),(r, r+1)])
    arrList[r][r], arrList[r+1][r+1= 22
    arrList[r+1][r], arrList[r][r+1= 11
 
    for position in posList:
        color = position[1]
        pos = position[0]
        color_list = white_list
 
        if color == 1:
            color_list = black_list
 
        changed = changeArr(arr, color_list, pos, color, n)
        for p in changed:
            arr[p[0]][p[1]] = color
 
        if color == 1# black
            black_list.update(changed)
            white_list.difference_update(changed)
 
        else:
        # white
            white_list.update(changed)
            black_list.difference_update(changed)
 
    return len(black_list), len(white_list)
 
 
if __name__ == "__main__":
    t = int(input().strip())  # test case count
    for i in range(t):
        n, m = map(int, input().strip().split())
        arrList = [["."]*for i in range(n)]
 
        # 흙돌이 선을 잡는다.
        posList = []
        for i2 in range(m):
            c, r, color = map(int, input().strip().split())
            pos = ((r - 1, c - 1), color)
            posList.append(pos)
 
        black, white = solve(posList, arrList, n)
        print('#{0} {1} {2}'.format(i+1, black, white))
 
cs

#sw expert 4615 #sw expert 4615 재미있는 오셀로 게임 #sw expert 4615. 재미있는 오셀로 게임 #삼성 재미있는 오셀로 게임 #SW Expert 재미있는 오셀로 게임 #재미있는 오셀로 게임 삼성 #재미있는 오셀로 게임 python #python 오셀로 게임 #줄기세포 배양 3차시#줄기세포 배양 문제들 #2차원 배열 탐색 오셀로 #파이썬 4615 재미있는 오셀로 게임 #4615. 재미있는 오셀로 게임 파이썬 #삼성 4615. 재미있는 오셀로 게임