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

     

    19235번: 모노미노도미노

    모노미노도미노는 아래와 같이 생긴 보드에서 진행되는 게임이다. 보드는 빨간색 보드, 파란색 보드, 초록색 보드가 그림과 같이 붙어있는 형태이다. 게임에서 사용하는 좌표 (x, y)에서 x는 행,

    www.acmicpc.net

     

    구현문제

    문제의 조건을 차근차근 살펴보자.

     

     

    블럭은 이렇게 총 세종류가 있다.

     

     

    블럭을 빨간색에 위치시키면 다음과 같이 배치된다.

    1 x 2 블록을 다시한번 배치했을 때에는 다음과 같은 모양이 된다.

    여기서 녹색보드의 (4, 0)부분에 블록이 걸쳐있는 것으로 보아 블록이 걸칠 경우 분리되어 떨어지지 않는다는 것을 볼 수 있다.

     

     

     

    초록색보드의 4번 행을보면 한줄이 모두 채워져 있음을 확인할 수 있다.

    이 경우 그 행에있는 블록들이 사라진다. 그 후 블록들이 테트리스하듯이 빈자리를 채우러 내려온다.

     

    녹색보드의 0, 1번행, 파란 보드의 0, 1번 열은 연한 색깔 보드판이며 만약 여기에 블록이 위치했을 경우

    각각 블럭이 존재하는 연한 보드의 녹색 보드의 경우 행, 파란 보드의 경우 열의 갯수에 따라 가장 구석 행, 열의 블록이 사라지고 한줄씩 이동된다.

     

     

    문제 설명은 문제에 나와있으니 간단히 하자.

    자세한 문제 내용은 문제를 읽어보는 것이 좋을 것 같다.

    이 문제에서 주의해야 할 점은 녹색보드에서의 1 x 2 블록, 파란보드에서의 2 x 1 블록으로 생각된다.

    이런식으로 중간에 빈공간이 생길 수 있게 배치되는 것이 가능한 블록이기 때문이다.

    반면에 녹색보드에서의 2 x 1 블록, 파란보드에서의 1 x 2 블록은 중간에 빈 공간이 생기는게 불가능하다.

    따라서 배치할 때를 제외하면 1 x 1 블록과 동일하게 취급해도 문제가 없다.

     

    함수를 여러개 구현해 문제를 해결하였는데 작동 순서는 다음과 같다.

     

    1. 블록을 놓는다.

    2. 채워져있는지 확인한 후 없앤다.

    3. 없어진 빈자리를 채운다. (위에서 주의해야한다고 했던 블록들을 주의하자)

    4. 연한 블록에 블록이 들어있을 경우를 처리한다.

     

    연한 블록에 블록이 존재할 경우에는 갯수를 세서 구석쪽 행, 열들을 필요한만큼 없애고 원하는 만큼 쉬프트 시키면된다. 임시 배열을 하나 만들어서 처리해주었다.

     

    아래는 소스코드이다.

    더보기
    #include <bits/stdc++.h>
    #define endl '\n'
    #define pb push_back
    #define mp make_pair
    #define MOD 1000000007
    #define cont continue
    #define rep(i, n) for(int i = 0 ; i < (n) ; i++)
    #define all(x) (x).begin(), (x).end()
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pii;
    typedef pair<ll,ll> pll;
    const ll INF = 987654321;
    
    int green[6][4] = {};
    int blue[4][6] = {};
    int ans = 0;
    int N;
    
    void putblock1(int y, int x) {
      int pos;
      for(int i = 0 ; i <= 5 ; i++) {
        if(green[i][x] == 0) {
          pos = i;
        }
        else break;
      }
      green[pos][x] = 1;
    
    
      for(int i = 0 ; i <= 5 ; i++) {
        if(blue[y][i] == 0) {
          pos = i;
        }
        else break;
      }
      blue[y][pos] = 1;
      return;
    }
    
    void putblock2(int y, int x) {
      int pos = 0;
      for(int i = 0 ; i <= 5 ; i++) {
        if(green[i][x] == 0 && green[i][x + 1] == 0) {
          pos = i;
        }
        else break;
      }
      green[pos][x] = 2;
      green[pos][x + 1] = 2;
      pos = 0;
      for(int i = 1 ; i <= 5 ; i++) {
        if(blue[y][i] == 0 && blue[y][i - 1] == 0) {
          pos = i;
        }
        else break;
      }
      blue[y][pos] = 1;
      blue[y][pos - 1] = 1;
    }
    
    void putblock3(int y, int x) {
      int pos = 0;
      for(int i = 1 ; i <= 5 ; i++) {
        if(green[i][x] == 0 && green[i - 1][x] == 0) {
          pos = i;
        }
        else break;
      }
      green[pos][x] = 1;
      green[pos - 1][x] = 1;
    
      pos = 0;
    
      for(int i = 0 ; i <= 5 ; i++) {
        if(blue[y][i] == 0 && blue[y + 1][i] == 0) {
          pos = i;
        }
        else break;
      } 
      blue[y][pos] = 3;
      blue[y + 1][pos] = 3;
    
    }
    
    void getscoregreen() {
      while(1) {
         bool clear = false;
    
         for(int i = 1 ; i <= 5 ; i++) {
            bool g = true;
            for(int j = 0 ; j < 4 ; j++) {
              if(green[i][j] == 0) g = false;
            }
            if(g) {
              ans++;
              clear = true;
              for(int j = 0 ; j < 4 ; j++) {
                green[i][j] = 0;
              }
            }
         }
    
         if(!clear) return;
    
         for(int i = 5 ; i >= 0 ; i--) {
          for(int j = 0 ; j < 4 ; j++) {
            int y = i;
            int x = j;
            if(green[i][j] == 1) {
              for(int k = i + 1 ; k <= 5 ; k++) {
                if(green[k][j] == 0) {
                  y = k;
                }
                else break;
              }
    
              green[i][j] = 0;
              green[y][j] = 1;
            }
    
            else if(green[i][j] == 2 && j != 3 && green[i][j + 1] == 2) {
              for(int k = i + 1 ; k <= 5 ; k++) {
                if(green[k][j] == 0 && green[k][j + 1] == 0) {
                  y = k;
                }
                else break;
              }
              green[i][j] = 0;
              green[i][j + 1] = 0;
              green[y][j] = 2;
              green[y][j + 1] = 2;
            } 
          }
         }
      }
    }
    
    void getscoreblue() {
      while(1) {
         bool clear = false;
         for(int i = 1 ; i <= 5 ; i++) {
            bool g = true;
            for(int j = 0 ; j < 4 ; j++) {
              if(blue[j][i] == 0) g = false;
            }
            if(g) {
              ans++;
              clear = true;
              for(int j = 0 ; j < 4 ; j++) {
                blue[j][i] = 0;
              }
            }
         }
    
         if(!clear) return;
    
         for(int i = 5 ; i >= 0 ; i--) {
          for(int j = 0 ; j < 4 ; j++) {
            int y = j;
            int x = i;
            if(blue[j][i] == 1) {
              for(int k = i + 1 ; k <= 5 ; k++) {
                if(blue[j][k] == 0) {
                  x = k;
                }
                else break;
              }
              blue[j][i] = 0;
              blue[j][x] = 1;
            }
    
            else if(blue[j][i] == 3 && j != 3 && blue[j + 1][i] == 3) {
              for(int k = i + 1 ; k <= 5 ; k++) {
                if(blue[j][k] == 0 && blue[j + 1][k] == 0) {
                  x = k;
                }
                else break;
              }
              blue[j][i] = 0;
              blue[j + 1][i] = 0;
              blue[j][x] = 3;
              blue[j + 1][x] = 3;
            }  
          }
         }
      }
    }
    
    void greencase() {
      bool f = false;
      int cnt = 0;
      for(int i = 0 ; i < 2 ; i++) {
        for(int j = 0 ; j < 4 ; j++) {
          if(green[i][j] >= 1 && i == 0) f = true;
          if(green[i][j] >= 1) {
            cnt++;
            break;
          }
        }
      }
      if(cnt == 0) return;
      if(cnt == 1 && f == true) {
        for(int i = 0 ; i < 4 ; i++) {
          green[1][i] = green[0][i];
          green[0][i] = 0;
        }
      }
      int newgreen[6][4] = {};
      if(cnt == 1) {
        for(int i = 2 ; i <= 5 ; i++) {
          for(int j = 0 ; j < 4 ; j++) {
            newgreen[i][j] = green[i - 1][j];
          }
        }
      }
      else if(cnt == 2) {
        for(int i = 2 ; i <= 5 ; i++) {
          for(int j = 0 ; j < 4 ; j++) {
            newgreen[i][j] = green[i - 2][j];
          }
        }
      }
    
      for(int i = 0 ; i < 6 ; i++) {
        for(int j = 0 ; j < 4 ; j++) {
          green[i][j] = newgreen[i][j];
        }
      }
    }
    
    void bluecase() {
      bool f = false;
      int cnt = 0;
      for(int i = 0 ; i < 2 ; i++) {
        for(int j = 0 ; j < 4 ; j++) {
          if(blue[j][i] >= 1 && i == 0) f = true;
          if(blue[j][i] >= 1) {
            cnt++;
            break;
          }
        }
      }
      if(cnt == 0) return;
      if(cnt == 1 && f == true) {
        for(int i = 0 ; i < 4 ; i++) {
          blue[i][1] = blue[i][0];
          blue[i][0] = 0;
        }
      }
      int newblue[4][6] = {};
      if(cnt == 1) {
        for(int i = 2 ; i <= 5 ; i++) {
          for(int j = 0 ; j < 4 ; j++) {
            newblue[j][i] = blue[j][i - 1];
          }
        }
      }
      else if(cnt == 2) {
        for(int i = 2 ; i <= 5 ; i++) {
          for(int j = 0 ; j < 4 ; j++) {
            newblue[j][i] = blue[j][i - 2];
          }
        }
      }
    
      for(int i = 0 ; i < 6 ; i++) {
        for(int j = 0 ; j < 4 ; j++) {
          blue[j][i] = newblue[j][i];
        }
      }
      return;
    }
    
    int main() {
      cin.tie(NULL);
      ios_base::sync_with_stdio(false); 
      cin >> N;
    
      while(N--) {
        int t, x, y;
        cin >> t >> y >> x;
    
        if(t == 1) {
          putblock1(y, x);
        }
        if(t == 2) {
          putblock2(y, x); 
        }
        if(t == 3) {
          putblock3(y, x);
        }
        getscoregreen();
        getscoreblue();
        greencase();
        bluecase();
      }
      cout << ans << endl;
    
      int sum = 0;
      for(int i = 0 ; i < 6 ; i++) {
        for(int j = 0 ; j < 4 ; j++) {
          if(green[i][j] > 0) sum++;
          if(blue[j][i] > 0) sum++;
        }
      }
      cout << sum << endl;
    } 
    

    'BOJ' 카테고리의 다른 글

    백준(BOJ) 19590 : 비드맨  (0) 2020.08.19
    백준(BOJ) 2638 : 치즈  (0) 2020.07.07
    백준(BOJ) 11867 : 박스 나누기 게임  (0) 2020.06.26
    백준(BOJ) 16234 : 인구 이동  (0) 2020.06.22
    백준(BOJ) 19238 : 스타트 택시  (0) 2020.06.22
    Posted by 엄태호