본문 바로가기
알고리즘 PS/백트래킹

[백준] 1987번 - 알파벳 (Java)(○)

by 백호루이 2022. 9. 2.
반응형

https://www.acmicpc.net/problem/1987

 

1987번: 알파벳

세로 R칸, 가로 C칸으로 된 표 모양의 보드가 있다. 보드의 각 칸에는 대문자 알파벳이 하나씩 적혀 있고, 좌측 상단 칸 (1행 1열) 에는 말이 놓여 있다. 말은 상하좌우로 인접한 네 칸 중의 한 칸으

www.acmicpc.net

 

<문제 분석>

1. 세로 R, 가로 C로 된 맵이 있고, 대문자 알파벳으로 채워져 있음.

2. (1, 1)에 말이 있는데 상/하/좌/우로 움직일 수 있음. 그런데 이동한 칸의 알파벳은 이전 위치의 알파벳들과 달라야지 이동이 가능함. 

3. 칸을 지날 때 마다 알파벳을 저장하는 배열이 필요하고, 새 알파벳과 비교하는 함수가 필요함.

4. 방문배열도 당연히 필요함.

5. dfs함수 파라미터는 좌표를 넘겨주자.

 

<풀이 후기>

1. 방문한 칸의 알파벳을 ArrayList에 하나씩 추가를 해서 새 칸의 알파벳과 비교해서 true/false를 리턴하는 식으로 구현을 했는데 예제는 다 통과했지만 제출시 실패하는 케이스가 있었다.

2. visited 배열과 알파벳 비교 함수를 2개 운영하는 것이 비효율적이기도 하기에 대부분 visited 배열을 알파벳 숫자만큼 26개 만들어서 반복 된 것인지 하나로 확인하는 것 같다.

3. 그리고 dfs에서는 count를 전역변수로 하는게 아니라 dfs파라미터로 같이 넘겨서 중간중간 max값으로 저장하는 방식을 선호하는 것 같다.

 

 

<코드 구현 #1>

더보기
import java.util.*;

/*
[백준] 1987번 - 알파벳 (Java)
*/

public class Main {
    static int R, C;
    static char A[][];
    static boolean visited[][];
    static boolean alpha[];    

    void InputData() {
        Scanner in = new Scanner(System.in);
        R = in.nextInt();
        C = in.nextInt();
        A = new char[R][C];
        for (int i=0; i<R; i++) {
            String str = in.next();
            A[i] = str.toCharArray();         
        }
    }
    
    int dx[] = {-1, 0, 1, 0};
    int dy[] = {0, 1, 0, -1};
    void DFS(int x, int y, int count) {
        alpha[A[x][y]-'A'] = true;//알파벳 방문처리      
        max = Math.max(max, count);
        for (int i=0; i<4; i++) {
            int nx = x + dx[i];
            int ny = y + dy[i];
            if (nx < 0 || nx >= R || ny < 0 || ny >= C) continue;//맵 범위 벗어나면
            if (alpha[A[nx][ny]-'A']) continue;//방문한 알파멧이면 스킵
            DFS(nx, ny, count+1);//다음칸에서 탐색 시작
            alpha[A[nx][ny]-'A'] = false;//다음 탐색을 위해 알파벳 방문처리 취소
        }
    }

    int max = 0;
    ArrayList<Character> list = new ArrayList<>();
    void Solve() {
        alpha = new boolean[26];
        DFS(0, 0, 1);
        System.out.println(max);
    }
    
	public static void main(String[] args) {
		Main m = new Main();
        m.InputData();
        m.Solve();
	}
}

<코드구현 #2>

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
import java.util.Queue;
import java.util.LinkedList;

/*
1. 같은 알파벳을 두번 지날 수 없으니 중복을 허용하지 않는 재귀함수이다.
  - 1차원 방문배열 사용(알파벳 26개)
2. 가지치기를 통한 재귀함수이니 백트래킹 알고리즘이다.
3. 가지치기
  - 맵 범위를 벗어나는 경우
  - 이미 방문한 알파벳인 경우
*/

public class Main {
    static int R, C;
    static boolean visited[];
    static char map[][];
    static int max_count = Integer.MIN_VALUE;
    static int dx[] = {-1, 0, 1, 0};
    static int dy[] = {0, 1, 0, -1};

    void DFS(int x, int y, int count) {
        int idx = map[x][y] - 'A';
        visited[idx] = true;
        max_count = Math.max(max_count, count);
        // 탐색시작
        for (int i=0; i<4; i++) {
            int nx = x + dx[i];
            int ny = y + dy[i];
            // 가지치기
            if (nx<0 || nx>=R || ny<0 || ny>=C) continue; // 범위 벗어나면 패스
            idx = map[nx][ny] - 'A';
            if (visited[idx]) continue; // 방문한 알파벳이면 패스
            // 탐색진행
            DFS(nx, ny, count+1);
            // 백트래킹으로 이전 노드로 복귀하면 다음을 위해 방문처리 취소
            visited[idx] = false;
            
        }
        
    }

	void Solve() {
        visited = new boolean[26];
        DFS(0, 0, 1);
        System.out.println(max_count);
	}

    void inputData() throws Exception {
        InputStreamReader reader = new InputStreamReader(System.in);
        BufferedReader br = new BufferedReader(reader);
        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 str = br.readLine();
            for (int j=0; j<C; j++) {
                //map[i][j] = Integer.parseInt(st.nextToken());
                map[i][j] = str.charAt(j);
            }
        }
    }

    public static void main(String[] args) throws Exception {
        Main m = new Main();
        m.inputData(); // 입력 받는 부분
        m.Solve();// 여기서부터 작성
    }
}

반응형

'알고리즘 PS > 백트래킹' 카테고리의 다른 글

[백준] 6603번 - 로또 (Java)  (1) 2022.12.11
[백준] 9663번 - N-Queen (Java)  (1) 2022.10.13

댓글