본문 바로가기

알고리즘 공부 및 문제 풀이/프로그래머스(PRO)

[pro] 프로그래머스 level3 60061 기둥과 보 설치 (Java) - 시뮬레이션

[문제]

https://school.programmers.co.kr/learn/courses/30/lessons/60061

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

[풀이]

시뮬레이션(구현) 문제.

 

기둥과 보가 같은 좌표에 설치될 수 있으므로 구현상의 편의를 위해 기둥, 보 배열을 분리해두었다.

1) 기둥을 설치하는 경우. 기둥이 바닥 위에 있거나, 보의 한 쪽 끝 부분 위에 있거나, 또 다른 기둥 위에 있는 조건을 만족하면 설치하고 count를 증가시킨다.

2) 보를 설치하는 경우, 보의 한 쪽 끝 부분이 기둥 위에 있거나, 양쪽 끝 부분이 다른 보와 동시에 연결되어 있다면 보를 설치하고 count를 증가시킨다.

3) 기둥과 보의 삭제하는 경우. 삭제 후 전체 배열을 돌며 설치가 되어있는데 설치 조건을 만족하지 못하는 기둥이나 보가 발견되면 삭제할 수 없는 구조물이므로 false를 반환하고 다시 설치 표시해준다. 삭제 가능하다면 count를 감소시킨다.

 

정답배열은 new int[count][3]으로 선언해서 전체 배열을 돌며 설치되어있는 기둥과 보 정보를 저장해준다.

 

주의할 점. 기둥과 보 설치 시 x, y 범위를 벗어나는 조건을 함께 고려해주지 않으면 런타임 에러가 발생한다.

 

[코드]

 

class Solution {
    boolean[][] pillar;
    boolean[][] beam;
    int count;
    public int[][] solution(int n, int[][] build_frame) {
        int[][] answer = {};
        //모든 명령어를 수행한 후 구조물의 상태를 return
        //r c 0-기둥 1-보 0-삭제 1-설치
        pillar = new boolean[n+1][n+1];
        beam = new boolean[n+1][n+1];
        
        for(int[] b:build_frame){
            int c = b[0];
            int r = b[1];
            int type = b[2];
            int constructionType = b[3];
            if(type==0){ //기둥
                if(constructionType==1 && canConstructPillar(r, c)){
                    //기둥 설치
                    pillar[r][c] = true;
                    count++;      
                }
                else if(constructionType==0){
                    pillar[r][c] = false;
                    if(!canDelete(n)){
                        pillar[r][c] = true;
                    }
                    else{
                        count--;
                    }
                }
            }
            else{ //보
                if(constructionType==1 && canConstructBeam(r, c)){
                    beam[r][c] = true;
                    count++;
                }
                else if(constructionType==0){
                    beam[r][c] = false;
                    if(!canDelete(n)){
                        beam[r][c] = true;
                    }
                    else{
                        count--;
                    }
                }
            }
        }
        
        answer = new int[count][3];
        int idx = 0;
        for(int c=0; c<=n; c++){
            for(int r=0; r<=n; r++){
                if(pillar[r][c]){
                    answer[idx][0] = c;
                    answer[idx][1] = r;
                    answer[idx++][2] = 0;
                }
                if(beam[r][c]){
                    answer[idx][0] = c;
                    answer[idx][1] = r;
                    answer[idx++][2] = 1;
                }
            }
        }
        
        return answer;
    }
    
    public boolean canDelete(int n){
        
        for(int i=0; i<=n; i++){
            for(int j=0; j<=n; j++){
                //기둥이나 보가 있는데, 설치조건을 만족하지 않는다면 false
                if(pillar[i][j] && !canConstructPillar(i, j)) return false;
                if(beam[i][j] && !canConstructBeam(i, j)) return false;
            }
        }
        return true;
    }
    
    public boolean canConstructPillar(int r, int c){
        //바닥 위, 다른 기둥 위, 보 위
        return r==0 || (r>0 && pillar[r-1][c]) || (c>0 && beam[r][c-1]) || beam[r][c];
    }
    
    public boolean canConstructBeam(int r, int c){
        //기둥 위, 보와 보 사이
        return (r>0 && pillar[r-1][c]) || (r>0 && pillar[r-1][c+1]) || (c>0 && beam[r][c-1] && beam[r][c+1]);
    }

}