[백준/BOJ] 백준 19235번 : 모노미노도미노

2021. 3. 25. 18:25알고리즘 문제풀이

www.acmicpc.net/problem/19235

 

19235번: 모노미노도미노

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

www.acmicpc.net

블록을 놓고 움직이는 함수 Put, 꽉 차서 제거 되고 내려오는 블록들은 내려오는 함수 Remove, 연한색 칸을 확인해서 연한색 칸에 블록이 있으면 움직이는 함수 Down를 만들어 문제를 해결했다. Remove 함수에서 1X1 블록이 아닌 경우도 고려하여 해당 칸과 연결된 칸을 확인하여 연결된 블록(1X2 또는 2X1 블록 일때)을 확인해야 된다.

 

코드

#include <iostream>
#include <algorithm>
#include <vector>
#include <utility>
#include <deque>
using namespace std;

int n;
vector<vector<int>> board(10, vector<int>(10, 0));
int dxdy[4][2] = { {0,0},{0,0},{0,1},{1,0} };
int dir[4][2] = { {0,-1},{-1,0},{0,1},{1,0} };
int result_score = 0;

int Cnt()
{
	int ret = 0;

	for (int i = 6; i <= 9; i++)
		for (int j = 0; j <= 3; j++)
			if (board[i][j] != 0)
				ret++;

	for (int j = 6; j <= 9; j++)
		for (int i = 0; i <= 3; i++)
			if (board[i][j] != 0)
				ret++;

	return ret;
}

void Put(int t, int x, int y, int number)
{
	pair<int, int> block1_original = make_pair(x, y);
	pair<int, int> block2_original = make_pair(x + dxdy[t][0], y + dxdy[t][1]);

	pair<int, int> block1;
	pair<int, int> block2;

	//초록색쪽으로 내리기
	block1 = block1_original;
	block2 = block2_original;
	while (block1.first <= 9 && block2.first <= 9 && board[block1.first][block1.second] == 0 && board[block2.first][block2.second] == 0)
	{
		block1.first++;
		block2.first++;
	}
	block1.first--;
	block2.first--;
	board[block1.first][block1.second] = number;
	board[block2.first][block2.second] = number;

	//파란색쪽으로 내리기
	block1 = block1_original;
	block2 = block2_original;
	while (block1.second <= 9 && block2.second <= 9 && board[block1.first][block1.second] == 0 && board[block2.first][block2.second] == 0)
	{
		block1.second++;
		block2.second++;
	}
	block1.second--;
	block2.second--;
	board[block1.first][block1.second] = number;
	board[block2.first][block2.second] = number;

}

bool Remove()
{
	bool ret = false;

	for (int i = 9; i >= 4; i--)
	{
		bool check = true;

		for (int j = 0; j <= 3; j++)
		{
			if (board[i][j] == 0)
			{
				check = false;
				break;
			}
		}

		//i행이 블록으로 다 차있을때
		if (check == true)
		{
			ret = true;
			result_score++;
			for (int j = 0; j <= 3; j++)
			{
				board[i][j] = 0;
			}
		}
	}

	//초록색 내리기
	for (int i = 9; i >= 4; i--)
	{

		for (int j = 0; j <= 3; j++)
		{
			//블록을 만났을때
			if (board[i][j] != 0)
			{
				pair<int, int> block1 = make_pair(-1, -1);
				pair<int, int> block2 = make_pair(-1, -1);

				int this_number = board[i][j];
				block1 = make_pair(i, j);

				//연결된 블록을 찾는다
				for (int d = 0; d < 4; d++)
				{
					pair<int, int> there = make_pair(block1.first + dir[d][0], block1.second + dir[d][1]);

					if (there.first >= 4 && there.first <= 9 && there.second >= 0 && there.second <= 3 && board[there.first][there.second] == this_number)
					{
						block2 = there;
					}
				}

				//연결된 블록이 없을때
				if (block2.first == -1 && block2.second == -1)
				{
					block2 = block1;
				}
				board[block1.first][block1.second] = 0;
				board[block2.first][block2.second] = 0;

				while (block1.first <= 9 && block2.first <= 9 && board[block1.first][block1.second] == 0 && board[block2.first][block2.second] == 0)
				{
					block1.first++;
					block2.first++;
				}
				block1.first--;
				block2.first--;
				board[block1.first][block1.second] = this_number;
				board[block2.first][block2.second] = this_number;
			}
		}

	}

	//파란색 없어지는 줄 확인
	for (int j = 9; j >= 4; j--)
	{
		bool check = true;

		for (int i = 0; i <= 3; i++)
		{
			if (board[i][j] == 0)
			{
				check = false;
				break;
			}
		}

		//i행이 블록으로 다 차있을때
		if (check == true)
		{
			ret = true;
			result_score++;
			for (int i = 0; i <= 3; i++)
			{
				board[i][j] = 0;
			}
		}
	}

	//파란색 내리기
	for (int j = 9; j >= 4; j--)
	{
		for (int i = 0; i <= 3; i++)
		{
			//블록을 만났을때
			if (board[i][j] != 0)
			{
				pair<int, int> block1 = make_pair(-1, -1);
				pair<int, int> block2 = make_pair(-1, -1);
				int this_number = board[i][j];
				block1 = make_pair(i, j);

				//연결된 블록을 찾는다
				for (int d = 0; d < 4; d++)
				{
					pair<int, int> there = make_pair(block1.first + dir[d][0], block1.second + dir[d][1]);

					if (there.first >= 0 && there.first <= 3 && there.second >= 4 && there.second <= 9 && board[there.first][there.second] == this_number)
						block2 = there;
				}

				//연결된 블록이 없을때
				if (block2.first == -1 && block2.second == -1)
					block2 = block1;

				board[block1.first][block1.second] = 0;
				board[block2.first][block2.second] = 0;

				while (block1.second <= 9 && block2.second <= 9 && board[block1.first][block1.second] == 0 && board[block2.first][block2.second] == 0)
				{
					block1.second++;
					block2.second++;
				}
				block1.second--;
				block2.second--;
				board[block1.first][block1.second] = this_number;
				board[block2.first][block2.second] = this_number;
			}
		}

	}

	return ret;
}

void Down()
{
	int green_cnt = 0; //연한색깔 몇줄에 블록이 있는지 확인
	int blue_cnt = 0;

	for (int i = 4; i <= 5; i++)
	{
		for (int j = 0; j <= 3; j++)
		{
			if (board[i][j] != 0)
			{
				green_cnt++;
				break;
			}
		}
	}

	for (int j = 0; j <= 3; j++)
	{
		deque<int> temp;
		for (int i = 9; i >= 4; i--)
		{
			temp.push_back(board[i][j]);
		}

		for (int i = 0; i < green_cnt; i++)
			temp.pop_front();
		for (int i = 0; i < green_cnt; i++)
			temp.push_back(0);

		for (int i = 9; i >= 4; i--)
		{
			board[i][j] = temp.front();
			temp.pop_front();
		}
	}

	for (int j = 4; j <= 5; j++)
	{
		for (int i = 0; i <= 3; i++)
		{
			if (board[i][j] != 0)
			{
				blue_cnt++;
				break;
			}
		}
	}

	for (int i = 0; i <= 3; i++)
	{
		deque<int> temp;
		for (int j = 9; j >= 4; j--)
		{
			temp.push_back(board[i][j]);
		}

		for (int j = 0; j < blue_cnt; j++)
			temp.pop_front();
		for (int j = 0; j < blue_cnt; j++)
			temp.push_back(0);

		for (int j = 9; j >= 4; j--)
		{
			board[i][j] = temp.front();
			temp.pop_front();
		}
	}


}

int main()
{
	cin.tie(NULL);
	ios_base::sync_with_stdio(false);

	cin >> n;

	for (int i = 0; i < n; i++)
	{
		int t, x, y;

		cin >> t >> x >> y;

		Put(t, x, y, i + 1);

		while (1)
		{
			bool check;
			check = Remove();

			//더 이상 꽉 차서 없어지는게 없을때
			if (check == false)
				break;
		}

		//연한색 칸 확인
		Down();
	}

	int result_cnt = Cnt();

	cout << result_score << "\n";
	cout << result_cnt;

	return 0;
}