https://www.acmicpc.net/problem/2186
2186번: 문자판
첫째 줄에 N(1 ≤ N ≤ 100), M(1 ≤ M ≤ 100), K(1 ≤ K ≤ 5)가 주어진다. 다음 N개의 줄에는 M개의 알파벳 대문자가 주어지는데, 이는 N×M 크기의 문자판을 나타낸다. 다음 줄에는 1자 이상 80자 이하의
www.acmicpc.net
코드설명
DFS(깊이우선탐색) + DP(Dynamic Programming) 를 활용하는 문제입니다.
문제에서 DFS를 활용해서 원하는 target 문자열을 찾는 부분은 쉽습니다.
이 문제에서 어려운점은 DP를 활용하는 방법입니다.
처음에는 DP를 단순하게 int[][][] dp 로 선언하고 안의 값들은 여전히 0 으로 둔채로 만약 0 이상의 값들일경우. 즉, 문자를 찾은경우에만 DP가 작동하도록 했습니다.
하지만, 위의 방식처럼 할경우 결국 어떠한 값도 존재하지 않을경우에는 모든 경우를 탐색합니다.
그렇기에, 처음에 DP[][][] 를 -1 로 모두 초기화 시킵니다.
두번째, DFS로 함수 시작시 해당 sR, sC, level을 방문했다는 의미로 DP[][][] = 0 으로 초기화 시킵니다.
이때 왜 Level을 굳이 활용하는가에 대한 궁금증이 생길 수 있는데, 같은 칸을 여러번 방문할 수 있기에 level을 선택해두어야 모든 경우를 다 확인할 수 있습니다. 만약 level이 없다면, 해당 칸에 한번 방문한다면 다시는 방문하지 못하겠습니다.
코드
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.Arrays; import java.util.StringTokenizer; public class Main { public static int N, M, K; public static int answer = 0; public static int[][] arr; public static int[][] map; public static int[] target; public static int[][][] dp; public static int[] dx = {-1,1,0,0}; public static int[] dy = {0,0,-1,1}; 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()); map = new int[N + 1][M + 1]; dp = new int[101][101][81]; for(int i=0; i<N;i++) { st = new StringTokenizer(br.readLine()); String input = st.nextToken(); for(int j=0;j<M;j++) { map[i][j] = input.charAt(j) - 'A'; } } st = new StringTokenizer(br.readLine()); String targetS = st.nextToken(); target = new int[targetS.length()]; for(int i=0;i<targetS.length();i++) { target[i] = targetS.charAt(i) - 'A'; } // for(int i=0;i<N;i++) { // for(int j=0;j<M;j++) { // System.out.print(" "+map[i][j]); // } // System.out.println(); // } // System.out.println(); // for(int i=0;i<targetS.length();i++) { // System.out.print(target[i]+ " "); // } // System.out.println(); for(int i=0;i<101;i++) { for(int j=0;j<101;j++) { Arrays.fill(dp[i][j], -1); } } for(int i=0;i<N;i++) { for(int j=0;j<M;j++) { if(map[i][j] == target[0]) { answer += simulate(1, i, j); } } } System.out.println(answer); } public static int simulate(int level, int sR, int sC) { if(dp[sR][sC][level] != -1) return dp[sR][sC][level]; if(level == target.length) return 1; //만약 끝까지 온 경우라면 1개 추가합니다. dp[sR][sC][level] = 0; int cnt = 0; for(int dir = 0; dir < 4; dir++) { for(int move = 1; move <= K; move++) { int nr = sR + dx[dir] * move; int nc = sC + dy[dir] * move; if(nr < 0 || nr >= N || nc < 0 || nc >= M) continue; // System.out.println(" "+target[level + 1] +" "+map[nr][nc]); if(target[level] == map[nr][nc] ) { cnt += simulate(level + 1, nr, nc); } } } return dp[sR][sC][level] = cnt; } }