19235: 모노미노도미노

ewillwin·2023년 7월 23일
0

Problem Solving (BOJ)

목록 보기
146/230

풀이 시간


구현 방식

  • "20061: 모노미노도미노 2" 문제와 다른 점은 아래와 같다
    1) 초록색 보드에서 점수를 얻고 행이 사라지거나, 파란색 보드에서 점수를 얻고 열이 사라진다면, 그 후에 "타일 단위로" 경계나 다른 블록을 만나기 전까지 내려줘야한다 (모래알처럼 우수수 떨어지는 게 아님)
    2) 연한 칸에 대한 처리를 마친 후에 한 번 더 get_score()과 gravity()를 호출하여 점수 획득과 행 또는 열 제거를 수행해주어야한다

  • 타일 단위로 중력을 받는 부분을 구현해주기 위해 타일의 type 별로 1, 2, 3의 숫자로 green, blue에 표시해주었다

  • gravity(color)
    -> green인 경우에는 tile이 2인 경우를 주의해야한다
    -> while문에서 green[row+1][j+1] == 0까지 만족하면 swap을 해주고, idx_flag를 이용해 다음 열은 pass 하도록 해줘야한다
    -> blue인 경우에는 tile이 3인 경우를 주의해야한다
    -> while문에서 blue[i+1][col+1] == 0까지 만족하면 swap을 해주고, idx_flag를 이용해 다음 행은 pass 하도록 해줘야한다

코드

import sys


green = [[0] * 4 for _ in range(10)]
blue = [[0] * 10 for _ in range(4)]

def move_green(t, x, y):
    if t == 1:
        while True:
            if x >= 10:
                green[x-1][y] = 1; break
            if green[x][y] != 0:
                green[x-1][y] = 1; break
            x += 1
    elif t == 2:
        while True:
            if x >= 10:
                green[x-1][y] = 2; green[x-1][y+1] = 2; break
            if green[x][y] != 0 or green[x][y+1] != 0:
                green[x-1][y] = 2; green[x-1][y+1] = 2; break
            x += 1
    elif t == 3:
        while True:
            if x >= 10:
                green[x-1][y] = 3; green[x-2][y] = 3; break
            if green[x][y] != 0:
                green[x-1][y] = 3; green[x-2][y] = 3; break
            x += 1

def move_blue(t, x, y):
    if t == 1:
        while True:
            if y >= 10:
                blue[x][y-1] = 1; break
            if blue[x][y] != 0:
                blue[x][y-1] = 1; break
            y += 1
    elif t == 2:
        while True:
            if y >= 10:
                blue[x][y-1] = 2; blue[x][y-2] = 2; break
            if blue[x][y] != 0:
                blue[x][y-1] = 2; blue[x][y-2] = 2; break
            y += 1
    elif t == 3:
        while True:
            if y >= 10:
                blue[x][y-1] = 3; blue[x+1][y-1] = 3; break
            if blue[x][y] != 0 or blue[x+1][y] != 0:
                blue[x][y-1] = 3; blue[x+1][y-1] = 3; break
            y += 1

def gravity(color):
    if color == "green":
        for i in range(10-2, 4, -1):
            idx_flag = -1
            for j in range(4):
                if idx_flag == j: continue
                if green[i][j] == 1 or green[i][j] == 3:
                    row = i
                    while True:
                        if 0 <= row+1 < 10 and green[row+1][j] == 0:
                            green[row+1][j] = green[row][j]; green[row][j] = 0
                            row += 1
                        else: break
                elif green[i][j] == 2: 
                    row = i
                    while True:
                        if 0 <= row+1 < 10 and green[row+1][j] == 0 and green[row+1][j+1] == 0:
                            green[row+1][j] = green[row][j]; green[row][j] = 0
                            green[row+1][j+1] = green[row][j+1]; green[row][j+1] = 0
                            row += 1
                        else: break
                    idx_flag = j+1 #다음 열은 pass

    elif color == "blue":
        for j in range(10-2, 4, -1):
            idx_flag = -1
            for i in range(4):
                if idx_flag == i: continue
                if blue[i][j] == 1 or blue[i][j] == 2:
                    col = j
                    while True:
                        if 0 <= col+1 < 10 and blue[i][col+1] == 0:
                            blue[i][col+1] = blue[i][col]; blue[i][col] = 0
                            col += 1
                        else: break
                elif blue[i][j] == 3:
                    col = j
                    while True:
                        if 0 <= col+1 < 10 and blue[i][col+1] == 0 and blue[i+1][col+1] == 0:
                            blue[i][col+1] = blue[i][col]; blue[i][col] = 0
                            blue[i+1][col+1] = blue[i+1][col]; blue[i+1][col] = 0
                            col += 1
                        else: break
                    idx_flag = i+1 #다음 행은 pass

def get_score(color):
    global total_score

    gravity_flag = False
    if color == "green":
        for i in range(10):
            check = 0
            for j in range(4):
                if green[i][j] == 0: break
                check += 1
            if check == 4:
                green[i] = [0, 0, 0, 0]
                total_score += 1
                gravity_flag = True
    elif color == "blue":
        for j in range(6, 10):
            check = 0
            for i in range(4):
                if blue[i][j] == 0: break
                check += 1
            if check == 4:
                for x in range(4):
                    blue[x][j] = 0
                total_score += 1
                gravity_flag = True

    return gravity_flag

def light_check(color):
    if color == "green":
        row_cnt = 0
        for i in range(4, 6):
            if sum(green[i]) != 0: row_cnt += 1
        for _ in range(row_cnt):
            for i in range(10-1, 4, -1):
                green[i] = green[i-1]
            green[4] = [0, 0, 0, 0]
    elif color == "blue":
        col_cnt = 0
        for j in range(4, 6):
            for i in range(4):
                if blue[i][j] != 0: col_cnt += 1; break
        for _ in range(col_cnt):
            for j in range(10-1, 4, -1):
                for i in range(4):
                    blue[i][j] = blue[i][j-1]
            for i in range(4):
                blue[i][4] = 0


N = int(sys.stdin.readline()[:-1])
cmd = []
for n in range(N):
    t, x, y = map(int, sys.stdin.readline()[:-1].split())
    cmd.append((t, x, y))

total_score = 0
for n in range(N):
    t, x, y = cmd[n]

    ##### 초록색 판 이동
    move_green(t, x, y)

    ##### 초록색 판 점수 획득 + 행 제거 (블록 단위로 내려가야함!)
    gravity_green_flag = get_score("green")
    if gravity_green_flag: gravity("green")
    
    ##### 초록색 연한 칸 확인 + 행 제거
    light_check("green")

    ##### 연한 칸 처리 이후 초록색 판 점수 획득 + 행 제거 (블록 단위로 내려가야함!)
    gravity_green_flag = get_score("green")
    if gravity_green_flag: gravity("green")
            
    ##############################################################################

    ##### 파란색 판 이동
    move_blue(t, x, y)

    ##### 파란색 판 점수 획득 + 열 제거 (블록 단위로 내려가야함!)
    gravity_blue_flag = get_score("blue")
    if gravity_blue_flag: gravity("blue")

    ##### 파란색 연한 칸 확인 + 열 제거
    light_check("blue")

    ##### 연한 칸 처리 이후 파란색 판 점수 획득 + 열 제거 (블록 단위로 내려가야함!)
    gravity_blue_flag = get_score("blue")
    if gravity_blue_flag: gravity("blue")

print(total_score)
count = 0
for i in range(6, 10):
    for j in range(4):
        if green[i][j] != 0: count += 1
for i in range(4):
    for j in range(6, 10):
        if blue[i][j] != 0: count += 1
print(count)
  • 근 200줄이다 윽

결과

  • IndexError: gravity 함수에서 "green + 타일이 2번인 경우"와 "blue + 타일이 3번인 경우"에 idx_flag 변수를 통해 다음 열 또는 행을 건너뛸 수 있도록 구현하여 해결함

  • 꽤 괜찮은 최적화다 짝짝짝 👏🏻👏🏻👏🏻
profile
💼 Software Engineer @ LG Electronics | 🎓 SungKyunKwan Univ. CSE

0개의 댓글