-
2186 문자판백준/DP 다이나믹 프로그래밍 2024. 8. 27. 22:18
dp 와 dfs 를 이용한다.
거꾸로 찾아나가는 방식이다.
BREAK 이 문자를 찾아나가야 할 때,
dp[1][2][3] = 위치(1,2) 에서 시작된 문자로
BREAK 문자열의 3번째 부터 끝 문자열까지 완성할 수 있는 경우의 수이다.
즉, AK 를 완성할 수 있는 경우의 수로,
KAKT
XEAS
YRWU
ZBQP위치 (1,2) 의 문자열 = A인데,
여기에서 좌,우,위, 아래로 움직여서 K가 있는 경우를 찾아보면 한 가지 경우를 찾을 수 있다.
때문에 dp[1][2][3] = 1 이다.
(1) 코드 설명
KAKT
XEAS
YRWU
ZBQP1)
BREAK에서 맨 처음 문자 B가 있는 위치(3,1)에서 dfs가 시작한다.
===============================
KAKT
XEAS
YRWU
ZBQP2)
(3,1)의 위치에서 좌,우,위,아래 방향으로 다음 글자인
R이 있는 위치 (2,1) 에서 또 dfs가 진행된다.
====================================
KAKT
XEAS
YRWU
ZBQP3)
(2,1)의 위치에서 좌,우,위,아래 방향으로 다음 글자인
E가 있는 위치 (1,1) 에서 또 dfs가 진행된다.
=======================================
4)
KAKT
XEAS
YRWU
ZBQP(1,1)의 위치에서 좌,우,위,아래 방향으로 다음 글자인
A가 있는 위치 (0,1) 에서 또 dfs가 진행된다.
============================================
5)
KAKT
XEAS
YRWU
ZBQP(0,1)의 위치에서 좌,우,위,아래 방향으로 다음 글자인
K가 있는 위치 (0,2) 에서 또 dfs가 진행된다.
==========================================
그런데 이제 마지막 글자이므로
이 경우는 값 1을 리턴한다.
그래서 dp[0][2][4] = 1 이다.
즉 위치 (0,2) 에서 A를 만들 수 있는 경우의 수가 1이다.
그러면 dp[0][1][3] 에는 1이 더해지게 된다.
즉, 위치 (0,1) 에서 AK를 만들 수 있는 경우가 1만큼 증가함.
이런 식으로 아래에서부터 위로 올라가는 형식으로 해결하면 된다.
맨 처음 dp 배열을 모두 -1 로 채운 이유는 방문하지 않았음을 표현하는 것이다.
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.Arrays; import java.util.StringTokenizer; public class Main { static char[][] board; static int dp[][][]; static int N; static int M; static int K; static String word; public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(br.readLine(), " "); N = Integer.parseInt(st.nextToken()); M = Integer.parseInt(st.nextToken()); K = Integer.parseInt(st.nextToken()); board = new char[N][M]; for (int i = 0; i < N; i++) { String input = br.readLine(); for (int j = 0; j < M; j++) { board[i][j] = input.charAt(j); } } word = br.readLine(); dp = new int[N][M][word.length()]; for (int i = 0; i < N; i++) { for (int j = 0; j < M; j++) { Arrays.fill(dp[i][j], -1); } } long count = 0; for(int i=0; i<N; i++) { for(int j =0; j<M; j++) { if(board[i][j] == word.charAt(0)){ count+=dfs(i,j,0); } } } System.out.println(count); } public static int dfs(int x, int y, int length) { if(dp[x][y][length]!=-1) { return dp[x][y][length]; } if(length == (word.length()-1)) { return dp[x][y][length]=1; } dp[x][y][length] = 0; int dx[] = {-1,1,0,0}; int dy[] = {0,0,-1,1}; for(int i=1; i<=K; i++) { for(int j=0; j<4; j++) { int nextX = x + dx[j]*i; int nextY = y + dy[j]*i; if(nextX>=0 && nextX<N && nextY>=0 && nextY<M) { if (board[nextX][nextY] == word.charAt(length+1)){ dp[x][y][length] += dfs(nextX, nextY,length+1); } } } } return dp[x][y][length]; } }
참고 블로그 : [알고리즘/백준] 2186번: 문자판 (JAVA) (velog.io)
[알고리즘/백준] 2186번: 문자판 (JAVA)
백준 2186번: 문자판 문제 입출력 문제 접근법 문제를 읽어보고 미로 찾기와 비슷한 유형의 문제라고 생각하며 풀이를 진행했다. 처음 문제를 풀며 신경 쓴 부분은 다음과 같다. 방향 배열 dx, dy를
velog.io
'백준 > DP 다이나믹 프로그래밍' 카테고리의 다른 글
1135 뉴스 전하기 (0) 2024.08.23 2156 포도주 시식 (0) 2024.08.09 10844 쉬운 계단 수 (0) 2024.08.07 1788 피보나치 수의 확장 (0) 2024.07.09 1915 가장 큰 정사각형 (0) 2024.06.26