DP를 정~~말 어려워하는 제가 어떻게 이해했는지 적어보겠습니다!😆
가로
파이프는 이전에 설치한 파이프가 가로
, 대각선
일때 설치할 수 있죠.세로
파이프는 이전에 설치한 파이프가 세로
, 대각선
일때 설치할 수 있어요.대각선
파이프는 이전에 설치한 파이프가 대각선
, 가로
, 세로
모든 경우에서 설치 가능해요.벽
을 고려해주어야 하는데요벽
이 없어야 하는건 당연한거니까, 대각선
파이프를 설치할때만 특별히 주의하시면 돼요~대각선
파이프를 설치하기 위해서는 아래 사진처럼 파이프를 새로 추가하려는 칸 뿐아니라 왼쪽
, 위쪽
또한 벽이 없어야 돼요! (즉, 아래 사진의 색칠된 칸 모양┘
에 벽이 없어야 돼요) 여기까지는 어렵지 않게 이해하셨죠😉?dp
라는 3차원 그래프에 담아보려고 해요! 우선 그림을 통해서 어떤식으로 담을지 보여드릴게요.우선 벽
유무에 관한 (문제에서는 '집의 상태'라고 하더라고요?) 집 그래프를 board
라고 할게요. board
는 그냥 input을 그대로 가져옵시다. (예시는 그냥 아무 예시나 가져와봤어요!)
이걸 바탕으로 dp
의 초기 상태를 가져와보면 다음과 같아요.
dp
로 표현해보면 아래와 같겠네요!가로
또는 세로
또는 대각선
파이프가 1개 존재한다는 말이겠네요! 흠...이해되시나요😮?dp
로 풀어봅시다!dp
에 표시해줍시다.가로
이기 때문에 1열에는 파이프의 끝이 오는 경우가 없다는 것을 금방 알아차릴 수 있을 거예요.board[1][1]
부터 처리해갈 거예요! 1행과 1열은 이미 3번, 4번 과정에서 다 처리를 해줬으니까~😉board
에서 벽
이 있는지 없는지 검사해보고 (가로
, 세로
, 대각선
) 파이프를 설치할 공간이 있는지 판단해요!dp
에 결과를 저장해줍니다!아직 이게 무슨말인지 살~짝 알듯말듯 하니까 다시 그림으로 차근차근 이해해봐요 :)
- 이게 살짝 헷갈릴수도 있는데.. 가장 중요한 것은!!
dp
에 저장되는 값은 파이프의 끝의 개수를 가리킨다는 점이에요!- 아래 사진에서
dp
를 왜 저렇게 표현했는지 완벽하게 이해하고 넘어가세요..!
[1] 먼저 벽의 유무를 고려해봐요.
0
으로 벽이 없죠? → 가로
, 세로
파이프를 설치할 공간이 있어요.0
이네요. → 대각선
파이프를 설치할 공간이 있어요. 가로
, 세로
, 대각선
파이프 모두 설치할 공간이 충분히 있네요!dp
를 갱신해주면 돼요.[2], [3] 각 파이프의 종류에 따라서 dp
를 갱신해줘요
가로
파이프는 이전 파이프가 가로
, 대각선
인 경우만 설치할 수 있다고 했죠?dp
값을 갱신해줍시다!가로
파이프 끝 개수]와 [왼쪽 칸의 대각선
파이프 끝 개수]를 더하면, [현재 가로
파이프의 끝 개수]가 되겠죠? (근데 실제로는 다 0
(아래 그림에서 노란색 칸 dp
)이여서 갱신한 값도 그대로 0
이네요~~)세로
파이프는,현재 칸의 세로 파이프의 끝 개수 = 위쪽 칸의 세로 파이프 끝 개수 + 위쪽 칸의 대각선 파이프 끝 개수
가 될 것이고...대각선
파이프를 놓는 경우에 대해서는현재 칸의 대각선 파이프의 끝 개수 = (왼쪽 위 대각선)칸의 가로 파이프 끝 개수 + (왼쪽 위 대각선)칸의 세로 파이프 끝 개수 + (왼쪽 위 대각선)칸의 대각선 파이프 끝 개수)
이런 방법으로 계속해서 dp
를 메모이제이션 방법으로 채워가시면 됩니다!
코드는 아래와 같아요. 코드를 이해할때 주의할 점은 dp
는 가로
, 세로
, 대각선
칸을 구현하기 위해 3차원 배열을 사용했어요. 설명은 아래에 써놨어요!
dp[0][row][col]
= 가로
파이프에 대한 dp
dp[1][row][col]
= 대각선
파이프에 대한 dp
dp[2][row][col]
= 세로
파이프에 대한 dp
# 0 → ─, 1 → /, 2 → |
def solution():
# 1행 미리 처리하기 → (3) 과정
dp[0][0][1] = 1
for i in range(2, N):
if board[0][i] == 0:
dp[0][0][i] = dp[0][0][i - 1]
# 왜 1행과 1열을 제외하는지는 (3), (4) 과정에서 봤었죠?
for r in range(1, N):
for c in range(1, N):
# (5) 과정
# 대각선 파이프를 추가하는 과정
if board[r][c] == 0 and board[r][c - 1] == 0 and board[r - 1][c] == 0:
dp[1][r][c] = dp[0][r - 1][c - 1] + dp[1][r - 1][c - 1] + dp[2][r - 1][c - 1]
# 가로, 세로 파이프를 추가하는 과정
if board[r][c] == 0:
dp[0][r][c] = dp[0][r][c - 1] + dp[1][r][c - 1]
dp[2][r][c] = dp[2][r - 1][c] + dp[1][r - 1][c]
# 최종 결과 출력
print(sum(dp[i][N - 1][N - 1] for i in range(3)))
N = int(input())
board = [list(map(int, input().split())) for _ in range(N)]
dp = [[[0 for _ in range(N)] for _ in range(N)] for _ in range(3)]
solution()
감사합니다ㅠㅠ 드디어 이해가 되네요