728x90
반응형
https://www.acmicpc.net/problem/1987
1987번: 알파벳
세로 R칸, 가로 C칸으로 된 표 모양의 보드가 있다. 보드의 각 칸에는 대문자 알파벳이 하나씩 적혀 있고, 좌측 상단 칸 (1행 1열) 에는 말이 놓여 있다. 말은 상하좌우로 인접한 네 칸 중의 한 칸으
www.acmicpc.net
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
import java.util.Scanner;
public class Main {
public static int r, c;
public static int arr[][];
public static int max = 0;
public static boolean check[] = new boolean[27];
public static void DFS(int i, int j, int cnt) {
if (check[arr[i][j]]) { // 중복되는 알파벳이 나오는 경우 리턴
if (cnt > max) {
max = cnt;
}
return;
} else {
check[arr[i][j]] = true;
// 좌
if (j - 1 >= 0) {
DFS(i, j - 1, cnt + 1);
}
// 우
if (j + 1 < c) {
DFS(i, j + 1, cnt + 1);
}
// 상
if (i - 1 >= 0) {
DFS(i - 1, j, cnt + 1);
}
// 하
if (i + 1 < r) {
DFS(i + 1, j, cnt + 1);
}
// 같은 알파벳이 나오면 부모노드로 돌아가야!, 다른 루트 탐색
check[arr[i][j]] = false;
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
r = sc.nextInt();
c = sc.nextInt();
arr = new int[r + 1][c + 1];
for (int i = 0; i < r; i++) {
String s = sc.next();
for (int j = 0; j < c; j++) {
arr[i][j] = s.charAt(j) - 'A';
}
}
DFS(0, 0, 0);
System.out.println(max);
}
}
|
cs |
백트래킹을 할 때 리턴하는 기준 (즉 한 turn이 끝나는 기준)이 행과 열이 r과 c보다 커질 때로 생각했는데
역시나 틀렸다 ^^ 그래서 다른 사람들이 쓴 코드를 찾아봤는데 알파벳이 중복으로 나왔을때를 기준으로 리턴을 해줬다. 특히 백트래킹 문제 특징이 이미 현재 노드를 방문했다면 부모노드로 돌아와야한다는 특징이 있다. (경로 재탐색 위함)
그래서 꼭 마지막에 checek[arr[i][j]]=false 해줘야한다! 만약 이 경로가 먹히지 않으면 다시 부모노드로 돌아와 다른 경로를 탐색해야하기 때문에 현재 탐색한 이력을 지워줘야하기 때문이다.
이 얘기를 왜했냐면 부모 노드로 돌아와야한다는 기준(리턴의 기준) 이 바로 알파벳이 중복될때이기 때문이다! 사실 그러니까 이 알고리즘 이름이 백트래킹인 것 같은데 난 백트래킹 문제를 7번째 푸는 지금에서야 깨달았다..ㅋㅋㅋㅋ ㅜㅜㅜㅜ
내 코드는 왜 틀렸을까?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
import java.util.Scanner;
public class Main {
public static int r, c;
public static int arr[][];
public static boolean visited[][];
public static int max = 0;
public static int[] dX = { -1, 1, 0, 0 };
public static int[] dY = { 0, 0, -1, 1 };
public static int check[];
public static void DFS(int i, int j, int cnt) {
if (cnt > max) {
max = cnt;
}
if (i >= r && j >= c) {
return;
} else {
if (check[arr[i][j]] == 0 && !visited[i][j]) {
visited[i][j] = true;
check[arr[i][j]]++;
for (int k = 0; k < 4; k++) {
int changeX = i + dX[k];
int changeY = j + dY[k];
if (changeX >= 0 && changeY >= 0 && changeX < r && changeY < c) {
DFS(changeX, changeY, cnt + 1);
}
}
}
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
r = sc.nextInt();
c = sc.nextInt();
arr = new int[r + 1][c + 1];
visited = new boolean[r][c];
for (int i = 0; i < r; i++) {
String s = sc.next();
for (int j = 0; j < c; j++) {
arr[i][j] = s.charAt(j) - 'A';
}
}
check = new int[27];
DFS(0, 0, 0);
System.out.println(max);
}
}
|
cs |
visited 2차원 배열 만들어서 똑같은 인덱스 방문했는지 확인해줬는데 이건 의미가 1도 없다. 그냥 알파벳 중복이 중요
앞서 말했듯이 부모노드로 돌아오는 기준을 아예 잘못잡았다.
728x90
반응형
'알고리즘 > 완전탐색' 카테고리의 다른 글
[java 백준] 골드 4/2580번 스도쿠 (0) | 2022.03.28 |
---|---|
[java 백준] 실버 2/ 6603번 로또 (0) | 2022.03.27 |
[java 백준]골드 5/5014번 스타트링크 (0) | 2022.03.21 |
[java 백준] 골드 5/1759번 암호 만들기 (0) | 2022.03.17 |
[java 백준] 실버 2 / 1182번 부분수열의 합 (0) | 2022.03.06 |
댓글