상세 컨텐츠

본문 제목

[백준 20061번] 모노미노도미노2(파이썬)

알고리즘 공부

by Tabris4547 2022. 4. 20. 22:23

본문

728x90

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

 

20061번: 모노미노도미노 2

모노미노도미노는 아래와 같이 생긴 보드에서 진행되는 게임이다. 보드는 빨간색 보드, 파란색 보드, 초록색 보드가 그림과 같이 붙어있는 형태이다. 게임에서 사용하는 좌표 (x, y)에서 x는 행,

www.acmicpc.net

문제난이도가 높지는 않았는데

이 문제는 이상한 버그(?)가 숨어져 있습니다.

 

우선 프로그램 동작을 설명하면 이렇습니다.

 

1. 블록을 넣는다.

2. 블록이 파란색과 초록색에 각각 들어간다.

(파란색은 오른쪽으로 그대로

초록색은 아래로 그대로 이동)

3. 만약 각각 0 1에 블록이 있다면

블록을 뒤로 빼준다.

4. 블록이 1자로 찰 때

(파란색은 열이 모두 찰 때

초록색은 행이 모두 찰 때)

제거해주고 점수를 올린다.

5. 터트린 줄을 정리하고 다음 블록 받는다.

 

이건 테트리스를 해보신 분들이라면 무슨 느낌인지

감이 오실 겁니다.

그래서 체감적으로 난이도는 높지 않았는데...

예상치못한 버그가 발생해서

디버깅하느라 시간을 전부 소비했었습니다.

 

 

https://www.acmicpc.net/board/view/76833

 

글 읽기 - <그림9> 에서 <그림10>으로 넘어갈 때 문제가 생깁니다.

댓글을 작성하려면 로그인해야 합니다.

www.acmicpc.net

 

도저히 원인을 찾지못해서

질문게시판도 찾아봤습니다.

해당 글에서도 다음과 같이

버그가 발생했습니다.

이걸 제가 어떻게 봤냐면 저의 코드도

비슷한 지점에서 버그가 났었기 때문입니다.

 

# 백준 20061번 모노미노도미노2
import sys

input = sys.stdin.readline

N = int(input())

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

score = 0

for time in range(N):
    print(time)
    t, x, y = map(int, input().split())
    if t == 1:
        x_len = 1
        y_len = 1
    elif t == 2:
        x_len = 1
        y_len = 2
    elif t == 3:
        x_len = 2
        y_len = 1
    # 초록색 이동
    out = 0
    if x_len == 1:
        max_x = 6
    else:
        max_x = 5

    for nx in range(0, max_x):
        flag = 0
        back_x = 0
        for gx in range(nx, nx + x_len):
            for gy in range(y, y + y_len):
                if green[gx][gy] == 1:
                    flag = 1
                    back_x = nx - 1
                    break
            if flag == 1:
                for px in range(back_x, back_x + x_len):
                    for py in range(y, y + y_len):
                        green[px][py] = 1
                out = 1
                break
        # 만약에 끝까지 갈 경우

        if nx == max_x - 1 and not flag == 1 and not out == 1:
            for px in range(nx, nx + x_len):
                for py in range(y, y + y_len):
                    green[px][py] = 1

        if out == 1:
            break

    # 파란색 이동
    out = 0
    if y_len == 1:
        max_y = 6
    else:
        max_y = 5

    for ny in range(0, max_y):
        flag = 0
        back_y = 0
        # 중간에 벽을 만나면 뒤로 한걸음 물러나고 더함
        for bx in range(x, x + x_len):
            for by in range(ny, ny + y_len):
                if blue[bx][by] == 1:
                    flag = 1
                    back_y = ny - 1
                    break

            if flag == 1:
                for px in range(x, x + x_len):
                    for py in range(back_y, back_y + y_len):
                        blue[px][py] = 1
                out = 1
                break
        # 끝까지 가는 경우
        if ny == max_y - 1 and not flag == 1 and not out == 1:
            for px in range(x, x + x_len):
                for py in range(ny, ny + y_len):
                    blue[px][py] = 1

        if out == 1:
            break

    # 특별한 공간에 칸이 채워질 경우
    # 파란색은 0 1 열에
    # 초록색은 0 1 행에

    for by in range(2):
        for bx in range(4):
            if blue[bx][by] == 1:
                # 하나씩 뒤로 밀려줌
                for nbx in range(4):
                    blue[nbx][1:6], blue[nbx][0] = blue[nbx][0:5], 0
                break

    flag = 0
    for gx in range(2):
        for gy in range(4):
            if green[gx][gy] == 1:
                flag = 1
                print(green)
                # 하나씩 아래로 감
                for gnx in range(5, 0, -1):
                    green[gnx] = green[gnx - 1]
                green[0] = [0, 0, 0, 0]
                break

    if flag == 1:
        print('s')
        print(green)
        print()

    # 점수 더하기
    # 파란색은 열이 다 꽉차면 지우고 +1
    # 초록색은 행이 다 차면 지우고 +1
    # 지운칸 기준으로 전부 한칸씩 이동

    for by in range(2, 6):
        for bx in range(4):
            if blue[bx][by] == 0:
                break
            if bx == 3:
                score += 1
                now = by
                for gby in range(now, 1, -1):
                    for gnx in range(4):
                        blue[gnx][gby] = blue[gnx][gby - 1]

    # print(green)
    for gx in range(2, 6):
        for gy in range(4):
            if green[gx][gy] == 0:
                break
            if gy == 3:
                score += 1
                now = gx
                # print(now)
                for gnx in range(now, 1, -1):
                    green[gnx] = green[gnx - 1]
                # print(green)
                # print()
    print(blue)
    print(green)
    print()

print(score)

# 칸의 갯수 출력
num = 0
for by in range(6):
    for bx in range(4):
        if blue[bx][by] == 1:
            num += 1
for gx in range(6):
    for gy in range(4):
        if green[gx][gy] == 1:
            num += 1

print(num)

제가 쓴 코드인데요

파란색 초록색 블록을 놓을 때

문제가 발생했습니다.

for문의 버그인가해서

쌩구현으로 바꿔서도 표현했었으나

여전히 버그가 남아있었습니다.

계속된 디버깅에도 결국 문제를 찾지못해

이 문제는 솔루션을 참고했습니다.

 

import sys

input = sys.stdin.readline


def check_blue(): #파란색칸을 체크하고 지우는 함수
    global ans
    for j in range(2, 6):
        cnt = 0
        for i in range(4):
            if b[i][j]:
                cnt += 1

        if cnt == 4:
            remove_blue(j)
            ans += 1


def check_green():#초록색칸을 체크하고 지우는 함수
    global ans
    for i in range(2, 6):
        cnt = 0
        for j in range(4):
            if g[i][j]:
                cnt += 1

        if cnt == 4:
            remove_green(i)
            ans += 1


def remove_blue(idx):
    for j in range(idx, 0, -1):
        for i in range(4):
            b[i][j] = b[i][j-1]
    for i in range(4):
        b[i][0] = 0


def remove_green(idx):
    for i in range(idx, 0, -1):
        for j in range(4):
            g[i][j] = g[i-1][j]
    for j in range(4):
        g[0][j] = 0


def move_blue(t, x): #파란색에 블록을 옮기는 함수
    global b
    y = 1
    if t == 1 or t == 2: #1*1 or 1*2 블록
        while True:
            if y + 1 > 5 or b[x][y+1]:
                b[x][y] = 1
                if t == 2:
                    b[x][y-1] = 1
                break
            y += 1

    else:
        while True:#2*1블록
            if y + 1 > 5 or b[x][y+1] != 0 or b[x+1][y+1] != 0:
                b[x][y], b[x+1][y] = 1, 1
                break
            y += 1

    check_blue()

    for j in range(2):#0,1칸 체크
        for i in range(4):
            if b[i][j]:
                remove_blue(5)
                break


def move_green(t, y):
    global g
    x = 1
    if t == 1 or t == 3:#1*1 or 2*1 블록
        while True:
            if x + 1 > 5 or g[x+1][y]:
                g[x][y] = 1
                if t == 3:
                    g[x-1][y] = 1
                break
            x += 1

    else: #1*2블록
        while True:
            if x + 1 > 5 or g[x+1][y] or g[x+1][y+1]:
                g[x][y], g[x][y+1] = 1, 1
                break
            x += 1

    check_green()

    for i in range(2):#0,1칸 체크
        for j in range(4):
            if g[i][j]:
                remove_green(5)
                break


tc = int(input())
b = [[0] * 6 for _ in range(4)]
g = [[0] * 4 for _ in range(6)]

ans = 0
for i in range(tc):
    t, x, y = map(int, input().split())
    move_blue(t, x)
    move_green(t, y)

cnt_b, cnt_g = 0, 0
for i in range(4):
    for j in range(2, 6):
        if b[i][j]:
            cnt_b += 1
for i in range(2, 6):
    for j in range(4):
        if g[i][j]:
            cnt_g += 1

print(ans)
print(cnt_b + cnt_g)

 

 

https://jae-eun-ai.tistory.com/12

 

백준20061 : 모노미노도미노2(Python)

https://www.acmicpc.net/problem/20061 20061번: 모노미노도미노 2 모노미노도미노는 아래와 같이 생긴 보드에서 진행되는 게임이다. 보드는 빨간색 보드, 파란색 보드, 초록색 보드가 그림과 같이 붙어있는

jae-eun-ai.tistory.com

https://hoyeonkim795.github.io/posts/20061-%EB%AA%A8%EB%85%B8%EB%AF%B8%EB%85%B8%EB%8F%84%EB%AF%B8%EB%85%B82-python-%ED%8C%8C%EC%9D%B4%EC%8D%AC/

 

[백준] #20061 모노미노도미노2 Python (파이썬)

모노미노도미노2

hoyeonkim795.github.io

https://chldkato.tistory.com/194

 

백준 20061 모노미노도미노 2 (파이썬)

https://www.acmicpc.net/problem/20061 20061번: 모노미노도미노 2 모노미노도미노는 아래와 같이 생긴 보드에서 진행되는 게임이다. 보드는 빨간색 보드, 파란색 보드, 초록색 보드가 그림과 같이 붙어있는

chldkato.tistory.com

 

이유는 잘 모르겠지만

왜 처음의 코드로 짜면

버그가 생기는지 참 의문이네요....

(그거 버그가 아니라 스끼린데???)

728x90

관련글 더보기

댓글 영역