티스토리 뷰

1. 문제 링크

www.acmicpc.net/problem/20061

 

20061번: 모노미노도미노 2

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

www.acmicpc.net

 

2. 문제 개요 및 풀이

kibbomi.tistory.com/172

 

boj, 백준) 19235. 모노미노도미노 ( C / C++ )

1. 문제 링크 www.acmicpc.net/problem/19235 19235번: 모노미노도미노 모노미노도미노는 아래와 같이 생긴 보드에서 진행되는 게임이다. 보드는 빨간색 보드, 파란색 보드, 초록색 보드가 그림과 같이 붙

kibbomi.tistory.com

이 글의 내용과 아주 비슷하다.

차이점은 블록이 한 줄 가득 차면 지워지게 되는데, 그때 위에 쌓여있던 블록이 경계를 내려갈 때까지 쭉 내려가느냐(중력 받는 것처럼 우수수수), 아니면 그냥 실제 진짜 테트리스처럼 한 줄만 딱 내려가느냐 그 차이다.

 

그래서 19235번의 코드를 재활용해서 지저분하긴 하다.

 

 

다른 부분의 풀이는 위의 링크를 눌러서 보시면 될 것 같습니다.

19235문제와 다른점을 코드로 나타내자면, 

void pull_right(int x)
{
	for (int j = x; j >= 4; --j)
		for (int i = 0; i < 4; ++i)
			row[i][j] = row[i][j - 1];
	return;
}





void pull_down(int y)
{
	for (int i = y; i >= 4; --i)
		for (int j = 0; j < 4; ++j)
			col[i][j] = col[i - 1][j];
		return;
}

이 두개의 함수를 추가해준 것입니다.(모노미노도미노 와 이 부분이 다른 것.)

기존의 블록이 깨질경우 멈춰야 할 때까지 우수수수 내려가는 게 아닌, 위의 반복문처럼 한 줄이 삭제될 경우 한 줄씩만 내려오면 되기 때문에, 추가했습니다. 위의 코드는 딱 한 줄만 끌어내립니다. 

 

그래서 기존의 문제에서는 한줄이 삭제되고 또 떨어지는 것에 의해서 삭제될 확률이 있기 때문에 그 부분을 처리해주어야 했지만, 이번 문제에서는 그런 경우가 없기 때문에 그에 따라 main함수도 while반복문을 쓰지 않고 풀 수 있었습니다.

 

2번에 링크로 걸어놨던 문제가 더 어렵고 이번 문제가 더 쉬운데다가 약간 포함되는 형식의 문제이기 때문에, 풀이는 2번의 링크를 타고 보셔도 될 것 같습니다.

 

 

3. 코드

밑의 코드는 정답이긴하나, 모노미노도미노 1의 코드를 재활용한 거라 코드를 보실 거면 모노미노도미노1의 코드를 보는 것을 추천드립니다. 

 

#include <cstdio>
using namespace std;

int row[4][10], col[10][4];	//map
int n, ans, score;

void put_block(int y, int x , int type)	//y : row, x : col
{
	if (type == 1){	
		// 1*1 block
		row[y][x] = col[y][x] = 1;
	}
	else if (type == 2) {	
		// 1*2 block
		row[y][x] = row[y][x + 1] = 1;
		col[y][x] = 2; col[y][x + 1] = -2;
	}
	else{
		// 2*1block
		row[y][x] = 3;	row[y + 1][x] = -3;
		col[y][x] = col[y + 1][x] = 1;
	}
}

void move_right(int y, int x)
{
	if (row[y][x] == 1){

		if (x < 9) 
			if (row[y][x + 1] == 0) {

				row[y][x] = 0;
				row[y][x + 1] = 1;

				move_right(y, x + 1);
			}
		
	}
	else if (row[y][x] == 3){
		if (x < 9) {
			
			if (row[y][x + 1] == 0 && row[y + 1][x + 1] == 0)
			{
				row[y][x] = row[y + 1][x] = 0;
				row[y][x + 1] = 3; row[y + 1][x + 1] = -3;

				move_right(y, x + 1);
			}
		}
	}
	return;
}
void push_right(int start, int end)
{
	//[start, end]
	for (int j = end; j >= start; --j)
		for (int i = 0; i < 4; ++i)
			if (row[i][j] != 0) 
				move_right(i, j);
	return;
}

void move_down(int y, int x)
{
	if (col[y][x] == 1){
		if (y < 9)
			if (col[y + 1][x] == 0){

				col[y][x] = 0;
				col[y + 1][x] = 1;

				move_down(y + 1, x);
			}
		
	}
	else if(col[y][x] == 2){
		if (y < 9)
			
			if (col[y + 1][x] == 0 && col[y + 1][x + 1] == 0){

				col[y][x] = col[y][x + 1] = 0;

				col[y + 1][x] = 2; col[y + 1][x + 1] = -2;
				move_down(y + 1, x);
			}
	}
	return;
}
void push_down(int start, int end)
{
	//[start, end]
	for (int i = end; i >= start; --i)
		for (int j = 0; j < 4; ++j) 
			if (col[i][j] != 0)
				move_down(i, j);
	return;
}

bool isfull_row(int y) {
	//if a row is full, then return true.
	for (int j = 0; j < 4; ++j)
		if (col[y][j] == 0)
			return false;

	return true;
}

bool isfull_col(int x) {

	for (int i = 0; i < 4; ++i)
		if (row[i][x] == 0)
			return false;

	return true;
}

void erase_row(int y)
{
	for (int j = 0; j < 4; ++j)
		col[y][j] = 0;

	return;
}
void pull_down(int y)
{
	for (int i = y; i >= 4; --i)
		for (int j = 0; j < 4; ++j)
			col[i][j] = col[i - 1][j];
		return;
}
void erase_col(int x)
{
	for (int i = 0; i < 4; ++i)
		row[i][x] = 0;

	return;
}
void pull_right(int x)
{
	for (int j = x; j >= 4; --j)
		for (int i = 0; i < 4; ++i)
			row[i][j] = row[i][j - 1];
	return;
}
bool warning_erea_row(int y)
{
		for (int j = 0; j < 4; ++j)
			if (col[y][j] != 0)
				return true;
	
	return false;
}
bool warning_erea_col(int x)
{
		for (int i = 0; i < 4; ++i)
			if (row[i][x] != 0)
				return true;

	return false;
}
int main()
{
	scanf("%d", &n);
	
	while (n--)
	{
		//t, row(x), col(y) -> t, row(y), col(x)
		int t, x, y;
		scanf("%d %d %d", &t, &y, &x);	

		//construct block
		//push initial block
		put_block(y, x, t);
		push_right(0, 3);

		
		push_down(0, 3);

		
		//row first
		
		for (int j = 6; j <= 9; ++j) {
			if (isfull_col(j)) {
				++score;
				erase_col(j);
				pull_right(j);
			}
		}
			
		int cnt = 9;
		if (warning_erea_col(5))
			erase_col(cnt--);
		
		if (warning_erea_col(4))
			erase_col(cnt--);

		//if (cnt != 9)
			//push_right(4, 8);
		if (cnt == 8)
			pull_right(9);
		if (cnt == 7) {
			pull_right(8);
			pull_right(9);
		}


		//col
		
		for (int i = 6; i <= 9; ++i) {
			if (isfull_row(i)) {
				++score;
				erase_row(i);
				pull_down(i);
			}
		}
		
		cnt = 9;

		if (warning_erea_row(5))
			erase_row(cnt--);

		if (warning_erea_row(4))
			erase_row(cnt--);

		//if (cnt != 9)
			//push_down(4, 8);
		if (cnt == 8)
			pull_down(9);
		if (cnt == 7) {
			pull_down(8);
			pull_down(9);
		}
	}

	for (int i = 6; i <= 9; ++i)
		for (int j = 0; j < 4; ++j)
		{
			if (col[i][j] != 0)
				++ans;
			if (row[j][i] != 0)
				++ans;
		}

	printf("%d\n%d",score, ans);

	return 0;
}

 

 

4. 결과

 

 

 

 

 

 

 

 

댓글
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
Total
Today
Yesterday