제약 사항이 너무 많다...
보자마자 빡시게 구현하겠구나 생각했다.
이런 문제 풀 때 가장 중요한 점은 잔머리 굴리면 안된다.
있는 그대로 모든 조건 활용해서 구현해야 한다..
<풀이>
1) 격자 설정하기
(먼저 2차원 격자를 설정해서 문제를 풀어야 하는데 이 부분에서는 문제 내용을 어떻게 표시할지 본인만의 방법으로 생각해내야 한다.)
n x n 격자지만 사실은 0을 포함하고 있기 때문에 길이는 n+1 이다.
기둥을 표시할 격자 gidung 과 보를 표시할 격자 boo 를 boolean 2차원 배열로 설정했다.
한편 문제에서 주어진 대로 (1,0) 이라는 좌표에 대해 생각해보자.
(1,0) 을 좌표 그대로 생각하면 x좌표가 1 이며 y좌표가 0 인점이 떠오를 것이다.
하지만, 이를 2차원 컴퓨터 배열로 생각하면 이야기가 달라진다. 1행의 0번째 원소이므로 우리가 흔히 생각하는 (1,0)의 좌표가 아니다. 즉 좌표가 90도 뒤집어진 형태다. 아래를 보면서 이해를 하자.
만약 (1,1) 이 true 라고 해보자. 이때 (1,1)은 1행 1번 원소다.
gidung 의 경우는 (1,1) 을 기점으로 오른쪽으로 기둥이 세워지도록 설정했다.
boo 의 경우는 (1,1) 을 기점으로 아래로 보가 세워지도록 설정했다.
그 이유는 아래 그림을 보면 이해될 것이다.
이제 위와 같은 그림으로 생각해야 한다.
2) 보 설치 조건
"보는 한쪽 끝 부분이 기둥 위에 있거나, 또는 양쪽 끝 부분이 다른 보와 동시에 연결되어 있어야 합니다."
위 조건에 따라 그대로 작성하면 된다.
만약 (x,y)에 보를 설치한다고 해보자. 빨간 기둥 2개중에 한개가 있거나 초록색 보 2개가 양쪽에 반드시 있으면 된다.
3) 기둥 설치 조건
"기둥은 바닥 위에 있거나 보의 한쪽 끝 부분 위에 있거나, 또는 다른 기둥 위에 있어야 합니다."
(x,y) 에 기둥을 세우기 위해서는 초록색 보 2개중에 하나라도 있거나 빨간 기둥이 있거나 y==0 (바닥) 이어야 한다.
4) 제거 알고리즘
일단 제거한다.
그다음 모든 기둥과 보가 올바르게 설치되어있는지 2), 3) 의 함수를 이용해 점검한다.
만약 문제가 있다면 제거를 할 수 없으므로 원상복원 한다.
문제 없다면 넘어간다.
<전체 코드와 결과>
import java.util.*;
class Solution {
static boolean[][] gidung;
static boolean[][] boo;
static int N;
static Deque<int[]> ansList = new ArrayDeque<>();
public int[][] solution(int n, int[][] build_frame) {
N = n+1;
gidung = new boolean[N][N]; for(int i=0;i<N;i++) gidung[i]=new boolean[N];
boo = new boolean[N][N]; for(int i=0;i<N;i++) boo[i] = new boolean[N];
for(int[] bf : build_frame){
if(bf[2]==1 && bf[3]==1){ // 보 설치
if(booCheck(bf[0],bf[1])){
boo[bf[0]][bf[1]] = true;
ansList.add(new int[]{bf[0],bf[1],1});
}
}
if(bf[2]==0 && bf[3]==1){ // 기둥 설치
if(gidungCheck(bf[0],bf[1])){
gidung[bf[0]][bf[1]]=true;
ansList.add(new int[]{bf[0],bf[1],0});
}
}
if(bf[2]==0 && bf[3]==0){ // 기둥 삭제
gidung[bf[0]][bf[1]]=false;
remove(bf[0],bf[1],bf[2]);
if(!allCheck()){
gidung[bf[0]][bf[1]] = true;
ansList.add(new int[]{bf[0],bf[1],bf[2]});
}
}
if(bf[2]==1 && bf[3]==0){ // 보 삭제
boo[bf[0]][bf[1]] =false;
remove(bf[0],bf[1],bf[2]);
if(!allCheck()){
boo[bf[0]][bf[1]] = true;
ansList.add(new int[]{bf[0],bf[1],bf[2]});
}
}
}
return ansListToAnswer();
}
static int[][] ansListToAnswer(){
Iterator<int[]> iterator = ansList.iterator();
int[][] ans = new int[ansList.size()][3];
int i=0;
while(iterator.hasNext()){
ans[i++] = iterator.next();
}
Arrays.sort(ans,(a,b)->{
if(a[0]!=b[0]) return a[0]-b[0];
else if(a[1]!=b[1])return a[1]-b[1];
else return a[2]-b[2];
});
return ans;
}
static boolean booCheck(int x, int y){
if(y==0) return false; //바닥
else if(gidung[x][y-1] || gidung[x+1][y-1]){ // 양쪽 기둥
return true;
}else if( x-1>=0 && x+1<N && boo[x-1][y] && boo[x+1][y]){ // 양쪽 보
return true;
}
return false;
}
static boolean gidungCheck(int x,int y){
if(y==0) return true; // 바닥
else if((x-1>=0 && boo[x-1][y]) || boo[x][y]) return true; // 한쪽 끝에 보
else if(y-1>=0 && gidung[x][y-1]) return true; //다른 기둥 위에
return false;
}
static void remove(int x,int y,int w){
int ansListSize = ansList.size();
for(int i=0;i<ansListSize;i++){
int[] tmp = ansList.pollFirst();
if(!(tmp[0]==x && tmp[1]==y && tmp[2]==w)){
ansList.addLast(tmp);
}
}
}
static boolean allCheck(){
Iterator<int[]> iterator = ansList.iterator();
while(iterator.hasNext()){
int[] tmp = iterator.next();
if(tmp[2]==1){
if(!booCheck(tmp[0],tmp[1])) return false;
}else{
if(!gidungCheck(tmp[0],tmp[1])) return false;
}
}
return true;
}
}
'algorithm' 카테고리의 다른 글
[JAVA] 오픈채팅방 (2019 kakao 프로그래머스) (0) | 2020.08.25 |
---|---|
[JAVA] 가사검색 (kakao 2020 프로그래머스) (0) | 2020.08.24 |
[JAVA] 메모리 사용량과 시간을 줄이는 간단한 아이디어 (0) | 2020.08.20 |
[JAVA] 토마토 (백준 7569) (0) | 2020.08.15 |
[JAVA] 촌수 계산 (백준 2644) (0) | 2020.08.14 |
댓글