2020_상_A_1_L14

Nitroblue 1·2025년 9월 3일

삼성 기출 풀이

목록 보기
28/73
post-thumbnail

2차원 테트리스

Simulation

평균 : 180'


sol : 131' 30''

  • 수행 시간 : 282ms
  • 메모리 : 24MB

New Skills

  • 딱히 새로운 기술을 터득한 건 없고, 그냥 꼼꼼하게 설계 다 하고 푸니까 쉽게 풀었다.
  • 과거에 들었던 조언중에 '우선 통과부터 한 다음에 최적화해라'가 떠올랐다. 처음에는 메모리 효율때문에 Red, Yellow Area를 다 나눠서 별개로 관리하려고 했는데, 그것보다 차라리 전체 맵을 만들어서 관리하는 게 약간의 메모리 효율보다 훨씬 유리하겠다는 생각에 빠르게 초기 전략을 수정한 게 컸다.
k = int(input())

blocks_info = []
for _ in range(k):
    blocks_info.append(list(map(int, input().split())))

# Block types. start index is 0, 0 fixed
b1 = [[0, 0]]
b2 = [
    [0, 0],
    [0, 1]
]
b3 = [
    [0, 0],
    [1, 0]
]
block_type = [[], b1, b2, b3]

# check each area filled as T/F
# red_area : 0 <= i <= 3, 6 <= j <= 9
# pink_area : 0 <= i <= 3,  4 <= j <= 5

# lemon_area : 4 <= i <= 5, 0 <= j <= 3
# yellow_area : 6 <= i <= 9, 0 <= j <= 3
tetris_area = [[False] * 10 for _ in range(10)]

def tetris():
    global score
    # block_info[0] : type / [1] : i / [2] : j
    for block_info in blocks_info:
        # ex) b2(--) -> [[1, 2], [1, 3]]
        cur_block_area = []
        si, sj = block_info[1], block_info[2]
        # get block_area before drop (is on blue area)
        for area in block_type[block_info[0]]:
            cur_block_area.append([si + area[0], sj + area[1]])

        # print(cur_block_area)

        red_drop(cur_block_area)
        yellow_drop(cur_block_area)
        check_pop()
        check_soft_area()

        #### debug ####
        # print('red')
        # for r in range(4):
        #     for c in range(4, 10):
        #         print(tetris_area[r][c], end=" ")
        #     print()
        # print()
        #
        # print('yellow')
        # for r in range(4, 10):
        #     for c in range(4):
        #         print(tetris_area[r][c], end=" ")
        #     print()
        # print()
        #### debug ####

    return


def red_drop(b_poses):
    dj = 1
    if len(b_poses) == 2:
        p1, p2 = b_poses[0], b_poses[1]
        # 바깥으로 벗어나지 않고, 다른 블록과 겹치지 않을 때까지 오른쪽으로 이동
        while p1[1] + dj < 10 and p2[1] + dj < 10 and not tetris_area[p1[0]][p1[1] + dj] and not tetris_area[p2[0]][p2[1] + dj]:
            dj += 1
        tetris_area[b_poses[0][0]][b_poses[0][1] + dj - 1] = True
        tetris_area[b_poses[1][0]][b_poses[1][1] + dj - 1] = True

    if len(b_poses) == 1:
        p = b_poses[0]
        while p[1] + dj < 10 and not tetris_area[p[0]][p[1] + dj]:
            dj += 1
        tetris_area[b_poses[0][0]][b_poses[0][1] + dj - 1] = True

def yellow_drop(b_poses):
    di = 1
    if len(b_poses) == 2:
        p1, p2 = b_poses[0], b_poses[1]
        # 바깥으로 벗어나지 않고, 다른 블록과 겹치지 않을 때까지 오른쪽으로 이동
        while p1[0] + di < 10 and p2[0] + di < 10 and not tetris_area[p1[0] + di][p1[1]] and not tetris_area[p2[0] + di][
            p2[1]]:
            di += 1
        tetris_area[b_poses[0][0] + di - 1][b_poses[0][1]] = True
        tetris_area[b_poses[1][0] + di - 1][b_poses[1][1]] = True

    if len(b_poses) == 1:
        p = b_poses[0]
        while p[0] + di < 10 and not tetris_area[p[0] + di][p[1]]:
            di += 1
        tetris_area[b_poses[0][0] + di - 1][b_poses[0][1]] = True
    return


def check_pop():
    global score
    # for red
    for c in range(6, 10):
        is_filled = True
        for r in range(4):
            # if col is not filled
            if not tetris_area[r][c]:
                is_filled = False
                break
        if is_filled:
            # else, pop and add score!
            score += 1
            q = 0
            while c - q >= 6:
                for row in range(4):
                    # 해당 열을 오른쪽으로 밀어주고
                    tetris_area[row][c - q] = tetris_area[row][c - q - 1]
                    # 혹시 모르니 이동했던 열은 전부 False로 바꾼다.
                    tetris_area[row][c - q - 1] = False
                q += 1

    # for yellow
    for r in range(6, 10):
        is_filled = True
        for c in range(4):
            # row is not filled
            if not tetris_area[r][c]:
                is_filled = False
                break
        if is_filled:
            # else, pop and add score!
            score += 1
            q = 0
            while r - q >= 6:
                for col in range(4):
                    tetris_area[r - q][col] = tetris_area[r - q - 1][col]
                    tetris_area[r - q - 1][col] = False
                q += 1


def check_soft_area():
    # for red
    for c in range(4, 6):
        for r in range(4):
            if tetris_area[r][c]:
                push = 0
                while 6 - c - push > 0:
                    for col in range(9, c, -1):
                        for row in range(4):
                            tetris_area[row][col] = tetris_area[row][col - 1]
                            # 혹시 모르니 이동했던 열은 전부 False로 바꾼다.
                            tetris_area[row][col - 1] = False
                    push += 1

    # for yellow
    for r in range(4, 6):
        for c in range(4):
            if tetris_area[r][c]:
                push = 0
                while 6 - r - push > 0:
                    for row in range(9, r, -1):
                        for col in range(4):
                            tetris_area[row][col] = tetris_area[row - 1][col]
                            tetris_area[row - 1][col] = False
                    push += 1

    return


def get_filled_area():
    global total_area
    # red_area
    for r in range(4):
        for c in range(6, 10):
            if tetris_area[r][c]:
                total_area += 1

    # yellow_area
    for r in range(6, 10):
        for c in range(4):
            if tetris_area[r][c]:
                total_area += 1

##################### Main #####################
score = 0
total_area = 0
tetris()
get_filled_area()
print(score)
print(total_area)

0개의 댓글