알고리즘/📌백준

백준: 알파벳 - ( permuation 방문처리 )

IMSfromSeoul 2021. 8. 20. 12:58

🏆 문제 정보

문제 유형 : 백트랙킹 / DFS

문제 난이도 : 중

📌 문제

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

시작위치는 (0,0) . 알파벳은 지나갔었던 알파벳을 지날 수 없을 때, 지날 수 있는 최대 count를 구하라.

📌 생각

문제 자체는 일반적인 dfs이지만, 지나간 것을 어떻게 표시할 지가 문제였다.

 

첫번째로 생각했던 것은 List를 선언해서 지나갈 때마다 List에 담고, 매 재귀호출마다 해당 list와 paramter인 r,c를 확인해서 겹치면 return 하고, 겹치지 않으면 진행하는 식으로 하려고 했다.

 

여기에는 2가지 문제가 있었다.

 

⚡️1. 방문처리

permutation을 먼저 생각해보자.

 

해당 count=3 일 때,

v[i] = true

다음 함수 호출

v[i] = false 를 해주어야 한다.

 

v[i]=false 이 부분이 헷갈렸다. 함수가 끝나는 부분이니까 해줘도 의미없지 않나? 라고 생각이 들 수 있는데

현재 함수가 호출스택으로 관리되고 있다는 것을 생각해야 한다.

3이 호출됐을 때, 호출이 끝나고 3을 false처리를 해주지 않으면 다른 부분에서 3을 호출할 수 없다.

마찬가지로 저 부분에서 방문처리를 해주지 않았었는데, 해당 부분처럼 방문처리 false를 해주지 않으면 되돌아 갔을 때의 count가 되지 않는다.

 

⚡️2. 시간 초과

위의 방식대로 하면  매 호출마다 모든 list를 순회하면서 겹치는 지 확인하고, 또한 호출이 끝나면 다시 list 안에서 해당 character을 찾고 삭제해야 하므로 시간이 오래걸린다. 그래서 시간초과가 됐다.

 

다른 방법으로 알파벳 26개고 중복이 안되니까 boolean[] 배열 26개를 선언한다.

해당 알파벳 값에서 'A'를 빼면 0~26사이에 수가 형성되므로, boolean[] 과 1대1 대응시켜서 알파벳을 표현한다.

static boolean[] v = new boolean[26];
...
v[map[x][y]-'A']=true;
cnt++;

for(int i=0;i<4;i++){
    int nx = x+dx[i];
    int ny = y+dy[i];

    dfs(nx,ny,list,cnt);
}
v[map[x][y]-'A']=false;

📌 코드

package src.backjoon.알파벳;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class MainV2 {

    static int N,M;
    static char[][] map;
    static int count;

    static boolean[] v = new boolean[26];

    static int[] dx = {-1,1,0,0};
    static int[] dy = {0,0,-1,1};

    public static void main(String[] args) throws FileNotFoundException {
        System.setIn(new FileInputStream("./src/backjoon/알파벳/input.txt"));

        Scanner sc = new Scanner(System.in);

        N = sc.nextInt();
        M = sc.nextInt();

        count=0;
        map = new char[N][M];

        for(int i=0;i<N;i++){
            char[] chars = sc.next().toCharArray();
            for(int j=0;j<M;j++){
                map[i][j] = chars[j];
            }
        }

        List<Character> list = new ArrayList<>();
        dfs(0,0,list,0);

        System.out.println(count);
    }

    private static void dfs(int x, int y, List<Character> list, int cnt) {
        if(isOut(x,y) || v[map[x][y]-'A']){
            count = Math.max(cnt,count);
            return ;
        }
        v[map[x][y]-'A']=true;
        cnt++;

        for(int i=0;i<4;i++){
            int nx = x+dx[i];
            int ny = y+dy[i];

            dfs(nx,ny,list,cnt);
        }
        v[map[x][y]-'A']=false;
    }

    static void print(){
        for(int i=0;i<N;i++){
            for(int j=0;j<M;j++){
                System.out.print(map[i][j] + " ");
            }
            System.out.println();
        }
    }

    static boolean checkAlphaIsRepeat(int r, int c, List<Character> list){
        for(Character character : list){
            if(map[r][c] == character) return true;
        }
        return false;
    }

    static boolean isOut(int nx, int ny){
        return nx<0 || nx>=N || ny <0 || ny >= M;
    }
}