[Programmers] 기둥과 보 설치

Date:

[Programmers] 기둥과 보 설치

Problem URL : 기둥과 보 설치

#include <string>
#include <vector>
#include <cstring>

using namespace std;

vector<vector<int>> solution(int n, vector<vector<int>> build_frame) {
    vector<vector<int>> answer;
    int visit[102][102];
    memset(visit, 0, sizeof(visit));
    
    for(int i = 0; i < build_frame.size(); i++) {
        int x = build_frame[i][0];
        int y = build_frame[i][1];
        int a = build_frame[i][2];
        int b = build_frame[i][3];
        if(b == 1) {
            if(a == 0) {
                // 기둥 설치 조건
                // 바닥이거나, 좌표에 위방향 기둥말고 하나라도 설치가 되어있어야 한다.
                if(y == 0 || (visit[x][y] & 14)) {
                    visit[x][y] |= 1;
                    visit[x][y+1] |= 2;
                }
            }else {
                // 보 설치 조건
                // 좌우에 밑으로 기둥이 설치되어있거나
                // 양쪽에 보가 있어야 한다.
                if(visit[x][y] & 2 || ((visit[x][y] & 8) && (visit[x+1][y] & 4)) || visit[x+1][y] & 2) {
                    visit[x][y] |= 4;
                    visit[x+1][y] |= 8;
                }
            }
        }else {
            if(a == 0){
                // 기둥 삭제 불가 조건
                // 위에 좌표에 아래, 위방향 기둥만 있을 때
                if(visit[x][y+1] == 3) continue;
                // 왼쪽에 보가 있고, 왼쪽보의 왼쪽밑에 기둥이 없으면서
                // 좌우로 보가 연결되어있지 않을 때
                if((visit[x][y+1] & 8) && !(visit[x-1][y+1] & 2)) {
                    if(!(visit[x-1][y+1] & 8) || !(visit[x][y+1] & 4)) continue;
                }
                // 오른쪽에 보가 있고, 오른쪽보의 오른쪽밑에 기둥이 없으면서
                // 좌우로 보가 연결되어있지 않을 때
                if((visit[x][y+1] & 4) && !(visit[x+1][y+1] & 2)) {
                    if(!(visit[x][y+1] & 8) || !(visit[x+1][y+1] & 4)) continue;
                }
                visit[x][y] &= 14;
                visit[x][y+1] &= 13;
            }else {
                // 보 삭제 불가 조건
                // 왼쪽 보가 존재하고 왼쪽 보의 좌우 밑 기둥이 없을 때
                if((visit[x][y] & 8) && !(visit[x-1][y] & 2) && !(visit[x][y] & 2)) continue;
                // 오른쪽 보가 존재하고 오른쪽 보의 좌우 밑 기둥이 없을 때
                if((visit[x+1][y] & 4) && !(visit[x+1][y] & 2) && !(visit[x+2][y] & 2)) continue;
                // 받치고 있던 기둥이 있고 삭제할 보에게만 의지하고 있을 때
                if(visit[x][y] == 5 || visit[x+1][y] == 9) continue;
                visit[x][y] &= 11;
                visit[x+1][y] &= 7;
            }
        }
    }
    for(int x = 0; x <= n; x++) {
        for(int y = 0; y <= n; y++) {
            if(visit[x][y] & 1){
                answer.push_back({x,y,0});
            }
            if(visit[x][y] & 4){
                answer.push_back({x,y,1});
            }
        }    
    }
    return answer;
}

Comments

비트마스크를 써서 좌표마다 기둥과 보 설치 정보를 나타내주었다.
(1: 위로 기둥, 2: 아래로 기둥, 4: 오른쪽으로 보, 8: 왼쪽으로 보)
삭제 구현이 상당히 까다로웠다…

그리고 크게 두 가지 실수를 해서 삽질을 했었다.
[1] 연산자 우선 순위를 착각했는데, 비트연산자보다 비교연산자가 우선순위가 높은 것을 기억하자. [2] visit에 쓰레기값(?)이 들어있어서 테케가 실패했었다. memset을 습관화 하도록 해야겠다.

댓글