Skip to content
This repository was archived by the owner on Mar 18, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 129 additions & 0 deletions BOJ/2048 (Easy)/wooyeol.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
"""
2048 (Easy)
https://www.acmicpc.net/problem/12100

풀이시간
14:11 ~ 15:02(오답)
4시간 정도 재 풀이 및 레퍼런스 참고 (실패)

- 실패한 풀이 -
"""
import sys
import copy

sys.setrecursionlimit(10 ** 6)

input = sys.stdin.readline

def oob(x,y,dx,dy):
return 0 <= x + dx < N and 0 <= y + dy < N
# return (0 > x + dx) or (x + dx > N) or (y + dy < 0) or (y + dy > N)

def swipe(direction, t_board):
# col,row
l_row, l_col = len(t_board), len(t_board[0])

# 상하좌우
directions = ((-1,0), (1,0), (0,-1), (0,1))
directions_increase = ((range(1,l_row), range(l_row-2,-1,-1), range(1, l_col),range(l_col-2,-1,-1)))

# 상 하 움직일 경우
if direction in (0, 1):
for c_idx in range(l_col):
is_combined = [False] * l_row
for r_idx in directions_increase[direction]:
x, y = r_idx, c_idx

# 빈칸이면 이동하지 않는다.
if t_board[x][y]:
# 주어진 방향으로 한 칸 이동
dx, dy = directions[direction]
nx, ny = x + dx, y + dy

# nx,ny가 보드를 벗어난 다면 Break
if not oob(x, y, dx, dy):
break

# print(nx, ny, x, y)

# 빈칸일 경우
if t_board[nx][ny] == 0:
t_board[nx][ny] = t_board[x][y]
t_board[x][y] = 0

# 같은 값이 있는 경우
if t_board[nx][ny] == t_board[x][y] and not is_combined[nx]:
t_board[nx][ny] *= 2
t_board[x][y] = 0
is_combined[nx] = True

print("\nAfter Swipe", direction)
for row in t_board:
print(*row)

# 좌 우 움직일 경우
elif direction in (2, 3):
for r_idx in range(l_row):
is_combined = [False] * l_col
for c_idx in directions_increase[direction]:
x, y = r_idx, c_idx

# 빈칸이면 이동하지 않는다.
if board[x][y]:
# 주어진 방향으로 한 칸 이동
dx, dy = directions[direction]
nx, ny = x + dx, y + dy

# nx,ny가 보드를 벗어난다면 Break
if not oob(x, y, dx, dy):
break

# 빈칸일 경우
if t_board[nx][ny] == 0:
t_board[nx][ny] = t_board[x][y]
t_board[x][y] = 0

# 같은 값이 있는 경우
if t_board[nx][ny] == t_board[x][y] and not is_combined[ny]:
t_board[nx][ny] *= 2
t_board[x][y] = 0
is_combined[ny] = True


max_value = -1

def dfs(repeat, board):
# 종료 조건
if repeat == 1:
global max_value

# flag = False
for row in board:
temp_max_value = max(row)
if temp_max_value > max_value:
# flag = True
max_value = temp_max_value
# if flag:
# print("\n",max_value)
# for row in board:
# print(*row)

return

temp = copy.deepcopy(board)
# 상 하 좌 우
for direction in range(4):
swipe(direction, temp)
dfs(repeat+1, temp)
temp = copy.deepcopy(board)



N = int(input())

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

dfs(0, board)
print(max_value)
97 changes: 97 additions & 0 deletions BOJ/2048 (Easy)/wooyeol2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
"""
2048 (Easy)
https://www.acmicpc.net/problem/12100

풀이시간
23:23 ~ 24:14(49분)
풀이 참조 : https://jeongchul.tistory.com/667

문제 조건
1 <= N <=20

시간 복잡도 : O(N^3 * 4 * 4 ^ 5)
O(32,768,000)

접근법
무슨 알고리즘으로 풀이 할 수 있을까? -> 시뮬레이션(백 트래킹)

- 시뮬레이션을 위한 함수들을 선언해주었습니다.
1. swipe : 한 행 혹은 칼럼의 값 중 0이 아닌 값들을 queue에 넣는 역할을 수행합니다 -> 한 쪽으로 쓸기
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저는 이걸 matrix 내부에서 while문으로 케이스에 따라 변환해서 구현했는데, 이렇게 구현하면 훨씬 쉽게 구현할 수 있다는 인사이트를 얻어갑니다..! 메모리 조건도 널널한데 이렇게 해볼 생각을 못했네요..! 아주 좋은 아이디어 같습니다.

2. merge : queue에 들어있는 값들을 모두 검사하며 동일한 값이 두 번 나오면 합치고 다른 값이 나온다면 다른 칸에 값 채우기
3. turn : 한 번의 턴을 의미하며 상하우좌를 기준으로 입력받은 방향으로 swipe 후 merge를 진행합니다.
4. dfs : 백 트래킹 기법을 통해 5번의 연산 후 최대 값을 찾습니다.
"""
import sys
import copy
from collections import deque

input = sys.stdin.readline

queue = deque()

def swipe(x, y):
if board[x][y]:
queue.append(board[x][y])
board[x][y] = 0


def merge(x, y, direction):
dx, dy = direction
while queue:
value = queue.popleft()
# 빈칸이라면 현재 값 채우기
if not board[x][y]:
board[x][y] = value
# 해당 칸의 값과 현재 값이 같다면 두배
elif board[x][y] == value:
board[x][y] *= 2
x, y = x+dx, y+dy
# 해당 칸의 값과 현재 값이 다르다면 다음 칸에 배치
elif board[x][y] != value:
x, y = x+dx, y+dy
board[x][y] = value


def turn(direct):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분이 코드 라인 측면에서의 최적화가 굉장히 잘 되었지만 가독성 측면에서 이해하기 어려운 부분이 많았던 것 같습니다. 코테에서는 메서드별로 docstring을 달아놓으시면 혹시 면접때 해당 코드를 참고하게 되더라도 금방 다시 리마인드 하기 편할 것 같아요!

# 상하우좌
directions_from = (0, N-1)
directions = ((1, 0), (-1, 0), (0, 1), (0, -1))
directions_increase = (range(1, N), range(N-2, -1, -1))

if direct in (0, 1):
for y in range(N):
for x in directions_increase[direct % 2]:
swipe(x, y)
merge(directions_from[direct % 2], y, directions[direct])
elif direct in (2, 3):
for x in range(N):
for y in directions_increase[direct % 2]:
swipe(x, y)
merge(x, directions_from[direct % 2], directions[direct])


def dfs(idx):
global board, answer

# 종료 조건
if idx == 5:
for i in range(N):
temp_max = max(board[i])
if temp_max > answer:
answer = temp_max
return

board_copy = copy.deepcopy(board)

for direct in range(4):
turn(direct)
dfs(idx + 1)
board = copy.deepcopy(board_copy)


N = int(input())
board = [list(map(int, input().split())) for _ in range(N)]
answer = 0

dfs(0)
print(answer)