https://www.acmicpc.net/problem/1987
1987번: 알파벳
세로 R칸, 가로 C칸으로 된 표 모양의 보드가 있다. 보드의 각 칸에는 대문자 알파벳이 하나씩 적혀 있고, 좌측 상단 칸 (1행 1열) 에는 말이 놓여 있다. 말은 상하좌우로 인접한 네 칸 중의 한 칸으
www.acmicpc.net
코드설명
DFS와 HashSet을 활용하여 해결합니다.
처음에 BFS로 착각하고 풀었습니다.
하지만, 문제조건을보면, 첫째 줄에 말이 지날 수 있는 최대의 칸 수를 출력한다.는 조건이 있습니다.
한개의 말을 깊이우선탐색을 진행하여 진행해야한다는 문제라는것을 알 수 있습니다.
문제에서 유의해야할점들입니다.
1. HashSet을 순회하는방법
- HashSet같은경우 향상된 for문을 통해 순회할 수 있습니다.
for(Character a : currentHashSet) { newHashSet.add(a); }
- HashMap같은경우 Map.entrySet을 통해 순회할 수 있습니다. ( HashMap 또한 향상된 for문 사용은 가능 )
2. HashSet은 기본적으로 얕은복사입니다. 깊은복사를 하고싶다면 순회하여 진행합니다.
HashSet<Character> HashSet = new HashSet<Character>(); HashSet<Character> newHashSet = HashSet; //얕은복사 이루어집니다. ( 주소를 참조 )
하지만, 이 문제에서 깊은복사를 통하여 진행하면, 시간초과가 나므로 얕은복사를 통해 HashSet의 값을 재귀가 끝난뒤 빼주면서 진행합니다.
코드
하나의 HashSet으로 전역적으로 관리합니다.
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.HashSet; import java.util.StringTokenizer; public class Main { public static int R, C; public static int answer = 0; public static char[][] map; public static HashSet<Character> hashset = new HashSet<>(); public static int[] dx = {-1,1,0,0}, 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()); R = Integer.parseInt(st.nextToken()); C = Integer.parseInt(st.nextToken()); map = new char[R][C]; for(int i=0;i<R;i++) { st = new StringTokenizer(br.readLine()); String inputAlphabet = st.nextToken(); for(int j=0;j<inputAlphabet.length();j++) { map[i][j] = inputAlphabet.charAt(j); } } hashset.add(map[0][0]); simulate(0, new Node(0, 0, 1)); System.out.println(answer); } public static void simulate(int level, Node start) { answer = Math.max(answer, start.moved); if(level >= R*C) { return ; } for(int dir = 0; dir < 4; dir++) { int nr = start.r + dx[dir]; int nc = start.c + dy[dir]; if(nr < 0 || nr >= R || nc < 0 || nc >= C) continue; if(hashset.contains(map[nr][nc]) == true) continue; hashset.add(map[nr][nc]); simulate(level + 1, new Node(nr, nc, start.moved + 1)); hashset.remove(map[nr][nc]); } } } class Node{ int r; int c; int moved; public Node(int r, int c, int moved) { this.r = r; this.c = c; this.moved = moved; } }
정답코드 ( DFS로 진행, HashSet 새로 생성하는것이 아닌 재귀함수가 끝나고 추가해준것 삭제 )
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.*; public class Main { public static int R, C; public static char[][] arr; public static int answer = 0; public static int[] dx = {-1,1,0,0}; public static int[] dy = {0,0,-1,1}; public static boolean[][] visited; public static void main(String[] args) throws IOException{ BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(br.readLine()); R = Integer.parseInt(st.nextToken()); C = Integer.parseInt(st.nextToken()); arr = new char[R][C]; visited = new boolean[R][C]; for(int i=0;i<R;i++) { st = new StringTokenizer(br.readLine()); arr[i] = st.nextToken().toCharArray(); } HashSet<Character> hashset = new HashSet<>(); hashset.add(arr[0][0]); simulate(new Node(0,0, hashset, 1)); System.out.println(answer); } public static void simulate(Node start) { int r = start.r; int c = start.c; int cnt = start.cnt; HashSet<Character> currentHashSet = start.hashset; answer = Math.max(answer, cnt); for(int dir = 0; dir < 4; dir++) { int nr = r + dx[dir]; int nc = c + dy[dir]; int nCnt = cnt + 1; if(nr < 0 || nr >= R || nc < 0 || nc >= C) continue; if(currentHashSet.contains(arr[nr][nc])) continue; currentHashSet.add(arr[nr][nc]); Node nNode = new Node(nr, nc, currentHashSet, nCnt); simulate(nNode); currentHashSet.remove(arr[nr][nc]); } } } class Node{ int r; int c; HashSet<Character> hashset; int cnt; public Node(int r, int c, HashSet<Character> hashset, int cnt) { this.r = r; this.c = c; this.hashset = hashset; this.cnt = cnt; } }
DFS로 진행하여 답은 맞지만, 시간초과가 나는 코드입니다.
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.*; public class Main { public static int R, C; public static char[][] arr; public static int answer = 0; public static int[] dx = {-1,1,0,0}; public static int[] dy = {0,0,-1,1}; public static boolean[][] visited; public static void main(String[] args) throws IOException{ BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(br.readLine()); R = Integer.parseInt(st.nextToken()); C = Integer.parseInt(st.nextToken()); arr = new char[R][C]; visited = new boolean[R][C]; for(int i=0;i<R;i++) { st = new StringTokenizer(br.readLine()); arr[i] = st.nextToken().toCharArray(); } HashSet<Character> hashset = new HashSet<>(); hashset.add(arr[0][0]); simulate(new Node(0,0, hashset, 1)); System.out.println(answer); } public static void simulate(Node start) { int r = start.r; int c = start.c; int cnt = start.cnt; HashSet<Character> currentHashSet = start.hashset; answer = Math.max(answer, cnt); for(int dir = 0; dir < 4; dir++) { int nr = r + dx[dir]; int nc = c + dy[dir]; int nCnt = cnt + 1; if(nr < 0 || nr >= R || nc < 0 || nc >= C) continue; if(currentHashSet.contains(arr[nr][nc])) continue; HashSet<Character> newHashSet = new HashSet<>(); for(Character a : currentHashSet) { newHashSet.add(a); } newHashSet.add(arr[nr][nc]); Node nNode = new Node(nr, nc, newHashSet, nCnt); simulate(nNode); } } } class Node{ int r; int c; HashSet<Character> hashset; int cnt; public Node(int r, int c, HashSet<Character> hashset, int cnt) { this.r = r; this.c = c; this.hashset = hashset; this.cnt = cnt; } }
첫째 줄에 말이 지날 수 있는 최대의 칸 수를 출력한다.는 조건이 있으므로 DFS로 한 말이 어디까지 갈 수 있는지 체크해야합니다.
처음에 BFS로 착각하고 푼 코드입니다.
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.*; public class Main { public static int R, C; public static char[][] arr; public static int answer = Integer.MAX_VALUE; public static int[] dx = {-1,1,0,0}; public static int[] dy = {0,0,-1,1}; public static boolean[][] visited; public static void main(String[] args) throws IOException{ BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(br.readLine()); R = Integer.parseInt(st.nextToken()); C = Integer.parseInt(st.nextToken()); arr = new char[R][C]; visited = new boolean[R][C]; for(int i=0;i<R;i++) { st = new StringTokenizer(br.readLine()); arr[i] = st.nextToken().toCharArray(); } simulate(); System.out.println(answer); } public static void simulate() { Queue<Node> q = new LinkedList<>(); HashSet<Character> hashsetTemp = new HashSet<Character>(); hashsetTemp.add(arr[0][0]); q.offer(new Node(0, 0, hashsetTemp)); answer = 1; while(!q.isEmpty()) { Node temp = q.poll(); int r = temp.r; int c = temp.c; HashSet<Character> hashset = temp.hashset; for(int dir = 0; dir < 4; dir++) { int nr = r + dx[dir]; int nc = c + dy[dir]; if(nr < 0 || nr >= R || nc < 0 || nc >= C) continue; if(hashset.contains(arr[nr][nc]) == true) continue; answer += 1; HashSet<Character> nHashSet = new HashSet<Character>(); for(Character a : hashset) { System.out.println("a:"+a); nHashSet.add(a); } System.out.println(); nHashSet.add(arr[nr][nc]); q.offer(new Node(nr, nc, nHashSet)); } } } } class Node{ int r; int c; HashSet<Character> hashset; public Node(int r, int c, HashSet<Character> hashset) { this.r = r; this.c = c; this.hashset = hashset; } }
'알고리즘 > 백준' 카테고리의 다른 글
[백준] 1027 고층 건물 - 구현(Implementation) + 기하학(Geometry) JAVA (0) | 2023.08.12 |
---|---|
[백준] 9935 문자열 폭발 - StringBuilder + 아이디어 JAVA (0) | 2023.08.12 |
[백준] 7490 0 만들기 - 완전탐색 + 문자열 + stringtokenizer JAVA (0) | 2023.08.11 |
[백준] 2138 전구와 스위치 - 그리디 + 아이디어 JAVA (0) | 2023.08.11 |
[백준] 14719 빗물 - 구현 + 시뮬레이션 JAVA (0) | 2023.08.10 |