백준 20061번 : 모노미노도미노2

Nitroblue 1·2026년 4월 10일

코딩테스트 준비

목록 보기
99/102

sol : 101' 09''

Learnings

  • 회전한 채로 그리드를 계속 생각하는 방식이 흥미로웠다.
#include <iostream>
#include <vector>
#include <utility>
using namespace std;

#define BLUE 0
#define GREEN 1

int n, score;
bool grids[2][6][4];
bool blocks[4][2][2] = {
	{},

	{{1, 0},
	{0, 0}},

	{{1, 1},
	{0, 0}},

	{{1, 0},
	{1, 0}}
};

void Debug(int zone) {
	if (zone == BLUE) cout << endl << "BLUE DEBUG" << endl;
	else if (zone == GREEN) cout << endl << "GREEN DEBUG" << endl;

	for (int i = 0; i < 6; i++) {
		for (int j = 0; j < 4; j++) {
			cout << grids[zone][i][j] << ' ';
		}
		cout << endl;
	}
	cout << "DEBUG FIN" << endl;
}

bool InGrid(int i, int j) {
	return 0 <= i && i < 6 && 0 <= j && j < 6;
}

bool Fit(vector<pair<int, int>>& area, bool grid[6][4]) {
	for (int a = 0; a < area.size(); a++) {
		int ci = area[a].first, cj = area[a].second;
		if (!InGrid(ci, cj) || grid[ci][cj]) return false;
	}
	return true;
}

bool RowFull(int zone, int i) {
	for (int j = 0; j < 4; j++) {
		if (grids[zone][i][j] == false) {
			return false;
		}
	}
	return true;
}

void Downward(int zone, int i) {
	for (int ci = i - 1; ci >= 0; ci--) {
		for (int cj = 0; cj < 4; cj++) {
			if (!grids[zone][ci][cj]) continue;

			grids[zone][ci][cj] = false;
			grids[zone][ci + 1][cj] = true;
		}
	}
}

void PushDown(int zone) {
	for (int i = 5; i > 0; i--) {
		for (int j = 0; j < 4; j++) {
			grids[zone][i][j] = grids[zone][i - 1][j];
			grids[zone][i - 1][j] = false;
		}
	}
}

void Drop(int zone, int type, int x, int y) {
	vector<pair<int, int>> curArea;
	for (int i = 0; i < 2; i++) {
		for (int j = 0; j < 2; j++) {
			if (!blocks[type][i][j]) continue;

			int ci = x + i, cj = y + j;
			curArea.push_back({ ci, cj });
		}
	}
	
	for (int a = 0; a < curArea.size(); a++) {
		if (zone == BLUE) {
			int temp = curArea[a].first;
			curArea[a].first = curArea[a].second - y;
			curArea[a].second = 4 - temp - 1;
		}
		else {
			curArea[a].first -= x;
		}
	}

	while (true) {
		if (!Fit(curArea, grids[zone])) break;
		for (int a = 0; a < curArea.size(); a++) {
			curArea[a].first++;
		}
	}

	for (int a = 0; a < curArea.size(); a++) {
		grids[zone][--curArea[a].first][curArea[a].second] = true;
	}

	// 1. 만약 행이 가득 찼다면
	for (int i = 5; i >= 0; i--) {
		bool full = RowFull(zone, i);

		while (full) {
			score++;
			for (int j = 0; j < 4; j++) {
				grids[zone][i][j] = false;
			}
			Downward(zone, i);
			full = RowFull(zone, i);
		}
	}

	// 2. 연한 칸에 존재한다면
	int downNum = 0;
	for (int j = 0; j < 4; j++) {
		if (grids[zone][0][j]) {
			downNum = 2;
			break;
		}
	}
	if (downNum == 0) {
		for (int j = 0; j < 4; j++) {
			if (grids[zone][1][j]) {
				downNum = 1;
				break;
			}
		}
	}

	for (int d = 0; d < downNum; d++) PushDown(zone);
}

void PrintBlockNum() {
	int cnt = 0;
	for (int zone = 0; zone < 2; zone++) {
		for (int i = 0; i < 6; i++) {
			for (int j = 0; j < 4; j++) {
				if (grids[zone][i][j]) cnt++;
			}
		}
	}

	cout << cnt;
}

int main() {
	cin.tie(0)->sync_with_stdio(0);
	cin >> n;

	for (int turn = 1; turn <= n; turn++) {
		int t, x, y;
		cin >> t >> x >> y;

		Drop(GREEN, t, x, y);

		Drop(BLUE, t, x, y);
	}

	cout << score << '\n';
	PrintBlockNum();

	return 0;
}

0개의 댓글