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;
}
}