본문 바로가기
코딩 테스트&알고리즘/백준 Gold

[파이썬 python] 백준 - 12100 2048(easy)

by 창현2 2021. 8. 10.

2048 (Easy) 성공

알고리즘 분류

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

 

12100번: 2048 (Easy)

첫째 줄에 보드의 크기 N (1 ≤ N ≤ 20)이 주어진다. 둘째 줄부터 N개의 줄에는 게임판의 초기 상태가 주어진다. 0은 빈 칸을 나타내며, 이외의 값은 모두 블록을 나타낸다. 블록에 쓰여 있는 수는 2

www.acmicpc.net

 


answer = 0
N = int(input())
board = [[0 for y in range(N)] for x in range(N)]
for x in range(N):
        board[x] = list(map(int,input().split()))
visited = [[0 for y in range(N)] for x in range(N)]

def up(next_b):
        for x in range(len(visited)):
                for y in range(len(visited)):
                        visited[x][y] = 0

        for x in range(1, len(next_b)):
                for y in range(len(next_b)):
                        tmp_x, tmp_y = x, y
                        while True:
                                if next_b[tmp_x-1][tmp_y] == 0:
                                        next_b[tmp_x-1][tmp_y] = next_b[tmp_x][tmp_y]
                                        next_b[tmp_x][tmp_y] = 0
                                        tmp_x -= 1
                                        if tmp_x <= 0:
                                                break
                                elif next_b[tmp_x-1][tmp_y] == next_b[tmp_x][tmp_y] and visited[tmp_x-1][tmp_y] == 0:
                                        next_b[tmp_x-1][tmp_y] *= 2
                                        next_b[tmp_x][tmp_y] = 0
                                        visited[tmp_x-1][tmp_y] = 1
                                        break
                                else:
                                        break
        return next_b

def down(next_b):
        for x in range(len(visited)):
                for y in range(len(visited)):
                        visited[x][y] = 0

        for x in range(len(next_b)-2, -1, -1):
                for y in range(len(next_b)):
                        tmp_x, tmp_y = x, y
                        while True:
                                if next_b[tmp_x+1][tmp_y] == 0:
                                        next_b[tmp_x+1][tmp_y] = next_b[tmp_x][tmp_y]
                                        next_b[tmp_x][tmp_y] = 0
                                        tmp_x += 1
                                        if tmp_x >= len(next_b)-1:
                                                break
                                elif next_b[tmp_x+1][tmp_y] == next_b[tmp_x][tmp_y] and visited[tmp_x+1][tmp_y] == 0:
                                        next_b[tmp_x+1][tmp_y] *= 2
                                        next_b[tmp_x][tmp_y] = 0
                                        visited[tmp_x+1][tmp_y] = 1
                                        break
                                else:
                                        break
        return next_b

def left(next_b):
        for x in range(len(visited)):
                for y in range(len(visited)):
                        visited[x][y] = 0

        for y in range(1, len(next_b)):
                for x in range(0, len(next_b)):
                        tmp_x, tmp_y = x, y
                        while True:
                                if next_b[tmp_x][tmp_y-1] == 0:
                                        next_b[tmp_x][tmp_y-1] = next_b[tmp_x][tmp_y]
                                        next_b[tmp_x][tmp_y] = 0
                                        tmp_y -= 1
                                        if tmp_y <= 0:
                                                break
                                elif next_b[tmp_x][tmp_y-1] == next_b[tmp_x][tmp_y] and visited[tmp_x][tmp_y-1] == 0:
                                        next_b[tmp_x][tmp_y-1] *= 2
                                        next_b[tmp_x][tmp_y] = 0
                                        visited[tmp_x][tmp_y-1] = 1
                                        break
                                else:
                                        break
        return next_b

def right(next_b):
        for x in range(len(visited)):
                for y in range(len(visited)):
                        visited[x][y] = 0

        for y in range(len(next_b)-2, -1, -1):
                for x in range(0, len(next_b)):
                        tmp_x, tmp_y = x, y
                        while True:
                                if next_b[tmp_x][tmp_y+1] == 0:
                                        next_b[tmp_x][tmp_y+1] = next_b[tmp_x][tmp_y]
                                        next_b[tmp_x][tmp_y] = 0
                                        tmp_y += 1
                                        if tmp_y >= len(next_b)-1:
                                                break
                                elif next_b[tmp_x][tmp_y+1] == next_b[tmp_x][tmp_y] and visited[tmp_x][tmp_y+1] == 0:
                                        next_b[tmp_x][tmp_y+1] *= 2
                                        next_b[tmp_x][tmp_y] = 0
                                        visited[tmp_x][tmp_y+1] = 1
                                        break
                                else:
                                        break
        return next_b

def new_b(b):
        new_b = [[0 for y in range(len(b))] for x in range(len(b))]
        for x in range(len(b)):
                for y in range(len(b)):
                        new_b[x][y] = b[x][y]
        return new_b

def dfs(b, cnt):
        global answer
        if cnt == 5:
                for x in range(len(b)):
                        answer = max(answer, max(b[x]))
                return

        for x in range(len(b)):
                answer = max(answer, max(b[x]))

        cnt += 1
        dfs(up(new_b(b)), cnt)
        dfs(down(new_b(b)), cnt)
        dfs(left(new_b(b)), cnt)
        dfs(right(new_b(b)), cnt)

def solution():
        global answer
        dfs(board, 0)
        print(answer)

solution()

 

후기

 샘숭 기출문제 문제집에 있어서 풀었다. 원래는 이런 구현 문제들을  빠른 시간 안에 풀어야한다고 하지만 시간이 좀 걸렸다.(문제 조조건 중에, 한번 합친것은 한 과정에서는 다시 합칠 수 없다 를 잘 못봐서 출력이 이상해졌다) 문제의 조건들과 제한사항들을 잘 이해하고, 재빠른 복붙이 답이다.

 

풀이

 * (재빠른 복사 붙여넣기가 핵심적이다)

 * 주의) 2차원 배열을 깊은 복사로 얕은 복사는 xx

 * 상하좌우를 DFS로 5번씩 돌아서 모든 경우의 수를 찾는다.

 

(1) DFS를 시작한다. DFS 인자로 보드(2차원 배열)을 받는다. 이것을 상하좌우로 각각 1번씩 이동시키고 cnt += 1

(2) 상하좌우로 이동한다. 이동할 곳이 0이라면, 계속 이동시킨다(board 범위 밖이라면 break). 이동할 곳이 자신과 같다면, 자기자신과 이동시킬 곳을 합쳐주고 break. 그 밖이라면 그냥 break. 이동시키는 것에서 주의할 점은, 한 번 합친 것은 한 과정에서는 다시 합칠 수 없다는 것이다. 이것을 위해서 visited를 사용하였고, 한번 합친 블록은 방문했다는 것을 표시하여 다시 방문하지 않도록 했다.(visited은 사용할 떄 미리 초기화)

(3) cnt 가 5번이 되었다면 DFS를 리턴한다.

'코딩 테스트&알고리즘 > 백준 Gold' 카테고리의 다른 글

[파이썬] 백준 - 내리막 길  (0) 2021.09.15
[c++] 백준 - 플로이드  (0) 2021.08.22
[c++] 백준 - 최단경로  (0) 2021.08.22

댓글