코딩테스트/문제

[BOJ] 16946번: 벽 부수고 이동하기 4

스키(ski) 2024. 4. 3. 09:24
문제 내용

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

 

16946번: 벽 부수고 이동하기 4

N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 한 칸에서 다른 칸으로 이동하려면, 두 칸이 인접해야 한다. 두 칸이

www.acmicpc.net

 

풀이 시간

45분

풀이 과정

문제에 써있는 방식 그대로 각 벽마다 BFS를 실행하였다. -> 시간초과

역으로 생각해서 빈곳들의 크기를 구하고 빈곳의 값을 개수로 넣어줬다.

이후 각 벽마다 사방의 빈곳의 개수의 합+1을 넣었다.-> 오답

=> 벽 주위의 빈곳들이 서로 연결되어 있는 경우를 고려하지 못했다.

Map을 사용해서 각 빈 그룹별 개수를 넣었다. 이후 빈곳의 값을 개수가 아닌 해당 키값을 넣었다.

 

이후 벽의 사방을 조회할때 사방의 그룹들의 키값을 유니크하게 가져오고 이를 Map에 조회해서 합을 구했다.

=> 정답!

 

정답 코드
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.*;


public class Main {
    static int N,M;
    static int[][]arr;
    static int[][]mv={{1,0},{-1,0},{0,1},{0,-1}};
    static Map<Integer,Integer> group=new HashMap<>();
    static int keyIndex=-1;

    public static void main(String[] args) throws Exception {
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st=new StringTokenizer(br.readLine());
        StringBuilder sb=new StringBuilder();
        N=Integer.parseInt(st.nextToken());
        M=Integer.parseInt(st.nextToken());

        arr=new int [N][M];

        for(int i=0;i<N;i++){
            char[] input=br.readLine().toCharArray();

            for(int j=0;j<M;j++){
                arr[i][j]=input[j]-'0';
            }
        }

        //fill
        for(int i=0;i<N;i++){
            for(int j=0;j<M;j++){
                if(arr[i][j]==0){
                    fill(i,j);
                }
            }
        }



        //check
        for(int i=0;i<N;i++){
            for(int j=0;j<M;j++){
                if(arr[i][j]==1){
                    int sum=0;
                    Set<Integer> s=new HashSet<>();
                    for(int[]next:mv){
                        int nx=i+next[0];
                        int ny=j+next[1];

                        if(nx<0||nx==N||ny<0||ny==M) continue;

                        if(arr[nx][ny]>0) continue;

                        s.add(arr[nx][ny]);
                    }

                    for(int x: s){
                        sum+=group.get(x);
                        sum%=10;
                    }

                    sb.append((sum+1)%10);
                }
                else{
                    sb.append(0);
                }
            }
            sb.append('\n');
        }

        System.out.println(sb);
    }

    static void fill(int x,int y){
        Set<Point> visited=new HashSet<>();
        Deque<Point> dq=new ArrayDeque<>();
        dq.add(new Point(x,y));
        visited.add(new Point(x,y));


        while(!dq.isEmpty()){
            Point cur=dq.poll();

            for(int[]next:mv){
                int nx=cur.x+next[0];
                int ny=cur.y+next[1];

                if(nx<0||nx==N||ny<0||ny==M) continue;

                Point nPoint=new Point(nx,ny);

                if(visited.contains(nPoint) || arr[nx][ny]!=0) continue;
                dq.add(nPoint);
                visited.add(nPoint);
            }
        }

        for(Point p:visited){
            arr[p.x][p.y]=keyIndex;
        }

        group.put(keyIndex--,visited.size());


    }

    static class Point{
        int x,y;

        public Point(int x,int y){
            this.x=x;
            this.y=y;
        }

        @Override
        public boolean equals(Object obj) {
            Point o=(Point) obj;

            return x==o.x&&y==o.y;
        }

        @Override
        public int hashCode() {
            return Objects.hash(x, y);
        }
    }


}

 

 

'코딩테스트 > 문제' 카테고리의 다른 글

[BOJ] 17142번: 연구소 3  (0) 2024.04.08
[BOJ] 2146번: 다리 만들기  (0) 2024.04.08
[BOJ] 20303번: 할로윈의 양아치  (0) 2024.04.02
[BOJ] 12026번: BOJ거리  (0) 2024.04.02
[백준] 15652번: N과 M (4)  (0) 2023.12.20