문제
https://www.acmicpc.net/problem/20061
20061번: 모노미노도미노 2
모노미노도미노는 아래와 같이 생긴 보드에서 진행되는 게임이다. 보드는 빨간색 보드, 파란색 보드, 초록색 보드가 그림과 같이 붙어있는 형태이다. 게임에서 사용하는 좌표 (x, y)에서 x는 행,
www.acmicpc.net
풀이 과정
1. 각 블록의 입력에 따라 초록색 보드와 파란색 보드에 새로운 블록을 추가한다. (대칭 관계 이용)
2. 블록이 추가된 상황에서 초록색 보드와 파란색 보드를 업데이트하는 함수
2-1. 보드의 한 Row(4칸)이 1로 가득 찬 경우 테트리스처럼 점수를 얻고 해당 줄을 삭제
2-2. 업데이트 직전 보드의 블록이 0, 1번 Row에 존재하면 밀어내어 0, 1번 Row를 비운다.
3. 업데이트하며 추가했던 score 값과 최종적으로 보드에 존재하는 칸의 수를 출력한다.
세부 풀이
(1) push_block 함수 (초록색 보드를 기준으로 작성) / update_block 함수
해당 함수를 구현할 때, 문제의 각 보드의 index에 주목했다.
초록색 보드의 인덱스는 배열[6][4]의 형태와 같았다. 하지만 파란색 보드의 경우 배열[4][6]의 형태로 초록색 보드의 각 좌표 대칭 형태의 모양이다. 주어지는 입력을 각 보드에 맞게 조정해 준다면 동일한 함수를 구현하여 초록색 보드와 파란색 보드에 블록을 추가하고 업데이트할 수 있을 것이라고 생각했다. 주어지는 블록의 입력 케이스도 단순한 3가지 경우였다. 따라서 초록색 보드의 형태에 맞게 push_block 함수를 구현한 뒤, 입력을 조절하여 처리하는 update_block 함수를 만들었다.
t=1 일 때, 1칸의 블록이 들어오는 경우에는 블록의 모양의 변경 없이 x, y 좌표만 바꾸어 입력한다. (Line 66 - Line 69)
2칸이 들어오게 된다면 t=2 모양은 t=3 모양으로, t=3 모양은 t=2 모양으로 바꾸어 파란색 보드를 업데이트한다.
t=3 일 때 파란색 보드의 모양과, t=2 일 때의 초록색 보드의 모양이 같은 것을 확인할 수 있다.
이런 대칭성을 바탕으로 push_block이라는 하나의 함수를 작성했다. (초록색 보드 기준)
시작점의 기준 index를 모두 1로 설정하였다. 블록을 추가한 뒤 무조건 0,1 Row는 비어있기 때문에 index를 1부터 시작하여 index+1 위치를 확인하며 진행하면 된다. 만약 새로운 위치의 값이 1 이거나 범위를 벗어난다면 반복문을 멈추고 해당 위치에 타입에 맞게 블록을 입력하면 된다. 이때 t=3 같은 경우는 가로방향이므로 v [index+1][y]와 v [index+1][y+1]을 같이 확인하며 반복문을 진행해야 한다.
(2-1) update_line의 꽉 찬 라인 지우기
이중 배열을 통해 한 번의 탐색을 통해 기존의 초록색 보드나, 파란색 보드의 상태 중 삭제되지 않는 부분만을 vector를 통해 저장한 뒤, 지워진 만큼 0으로 구성된 Row를 추가한 뒤 vector에 저장되어 있는 정보들을 보드에 이어서 저장했다.
(2-2) update_line의 라인 밀어 내기
꽉 찬 라인을 지운 뒤에도 Row 0,1에 블록이 남아 있다면 마지막 Row부터 밀어내며 Row 0, 1을 비우는 과정이다. 두 Row를 탐색하며 블록이 존재하면 line_push_cnt 변수를 증가시킨 뒤 break 하여 두 Row에 대해서 탐색을 진행했다. ( 0 <=line_push_cnt <= 2 )
(3)
N번의 반복을 진행한 뒤, update_line을 통해 증가된 score의 값과 최종 보드의 형태에 존재하는 블록의 칸 수를 출력한다.
소스 코드
#include <iostream>
#include <vector>
using namespace std;
int green[6][4];
int blue[6][4];
int N, score;
struct txy{
int t,x,y;
};
vector<txy> txy_v;
void print_map(int v[6][4]){
for(int i=0; i<6; i++){
for(int j=0;j<4;j++){
cout << v[i][j] << " ";
}
cout << "\n";
}
cout <<"\n";
}
void Input(){
cin >> N;
txy one;
for(int i=0;i<N;i++){
cin >> one.t >> one.x >> one.y;
txy_v.push_back(one);
}
}
//초록색을 기준으로 작성
void push_block(int t, int x, int y, int v[6][4]){
int newX=1;
if(t==1){
while(v[newX+1][y]!=1 && (newX+1<=5)){
newX++;
}
v[newX][y]=1;
}
else if(t==2){
while((v[newX+1][y]!=1 && v[newX+1][y+1]!=1) && (newX+1<=5)){
newX++;
}
v[newX][y]=1;
v[newX][y+1]=1;
}
else if(t==3){
while((v[newX+1][y]!=1) && (newX+1<=5)){
newX++;
}
v[newX][y]=1;
v[newX-1][y]=1;
}
}
void update_block(int t, int x, int y){
if(t==1){
push_block(t,x,y, green);
push_block(t,y,x, blue);
}
if(t==2){
push_block(t,x,y, green);
push_block(3,y,x, blue);
}
if(t==3){
push_block(t,x,y, green);
push_block(2,y,x, blue);
}
}
//꽉찬 라인 지우기 후, line 밀어내기 수행
void update_line(int v[6][4]){
//꽉찬 라인 지우기
vector< vector<int>> temp_vectors;
int delete_cnt=0;
int cnt;
for(int i=0;i<=6;i++){
cnt = 0;
vector<int> temp;
for(int j=0;j<4;j++){
temp.push_back(v[i][j]);
if(v[i][j]==1) cnt++;
}
if(cnt==4){
delete_cnt++;
score++;
continue;
}
else{
temp_vectors.push_back(temp);
}
}
int idx=0;
for(int i=0;i<6;i++){
if(i<delete_cnt){
for(int j=0;j<4;j++) v[i][j]=0;
}
else{
for(int j=0;j<4;j++) v[i][j]=temp_vectors[idx][j];
idx++;
}
}
//라인 밀어내기
int line_push_cnt=0;
for(int i=0;i<2;i++){
for(int j=0;j<4;j++){
if(v[i][j]!=0) {
line_push_cnt++;
break;
}
}
}
while(line_push_cnt--){
for(int i=4;i>=0;i--){
for(int j=0;j<4;j++){
v[i+1][j]=v[i][j];
}
}
for(int j=0;j<4;j++){
v[0][j]=0;
}
}
}
void solve(){
for(int i=0;i<N;i++){
txy one = txy_v[i];
update_block(one.t,one.x,one.y);
update_line(green);
update_line(blue);
}
int total_tiles=0;
for(int i=0;i<6;i++){
for(int j=0;j<4;j++){
if(green[i][j]==1) total_tiles++;
if(blue[i][j]==1) total_tiles++;
}
}
cout << score << "\n" << total_tiles << "\n";
}
int main(){
ios_base::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
Input();
solve();
return 0;
}
결과 및 후기
'코딩테스트 준비 > BOJ (Baekjoon Online Judge)' 카테고리의 다른 글
[백준 19238][C++] 스타트 택시 (0) | 2022.07.20 |
---|---|
[백준 19237][C++] 어른 상어 (0) | 2022.07.19 |
[백준 17825][C++] 주사위 윷놀이 (0) | 2022.07.15 |
[백준 17822][C++] 원판 돌리기 (0) | 2022.07.14 |
[백준 17142][C++] 연구소 3 (0) | 2022.07.13 |