Study hard

(C++)백준 20061번: 모노미노도미노 2 본문

백준/시뮬레이션,구현

(C++)백준 20061번: 모노미노도미노 2

Nimgnoej 2021. 4. 21. 16:58

www.acmicpc.net/problem/20061

 

20061번: 모노미노도미노 2

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

www.acmicpc.net

 

[풀이]

문제에 적힌 조건들을 구현하는 문제였다.

빨간색 보드와 초록색, 파란색 보드를 모두 한 배열로 구현하지 않고, 6*4초록색보드 배열과 4*6파란색보드 배열을 따로 만들어 사용했다.

블록을 놓은 위치를 받아 먼저 초록색 보드와 파란색 보드에 블록을 옮겨줬다. 그리고 while문을 두 개 중첩하여 먼저 해이나 열이 타일로 가득 찬 경우가 없을 때까지 점수를 획득하도록 하였다.

꽉찬 행이나 열이 없으면 특별한 칸에 블록이 있는지, 있으면 몇행 또는 몇열을 차지하는지 반환하여 초록색 보드의 경우는 5-(연한칸의 블록이 있는 행 개수)행부터 그 행의 개수만큼 아래로 내려줬고, 파란색 보드는 같은 연산을 행을 열로 바꾸어서 해주었다.

※특별한 칸에 블록이 있는 경우 그 개수를 세서 모든 행이나 열에 대해 한번에 내려주지 않으면 시간초과가 난다!

 

#include <iostream>
#include <vector>
using namespace std;

struct Pos {
	int t;
	int x, y;
};

int N;
int Green[6][4];
int Blue[4][6];
vector<Pos>Block;//블록 놓은 정보
int score = 0;

void greenBlock(int t, int y) {
	//1*1
	if (t == 1) {
		int gx = 0;
		while (gx < 6) {
			if (Green[gx][y] != 0)
				break;
			gx++;
		}
		gx--;
		Green[gx][y] = 1;
	}
	//1*2
	else if (t == 2) {
		int gx = 0;
		while (gx < 6) {
			if (Green[gx][y] != 0 || Green[gx][y + 1] != 0)
				break;
			gx++;
		}
		gx--;
		Green[gx][y] = 1;
		Green[gx][y + 1] = 1;
	}
	//2*1
	else if (t == 3) {
		int gx = 0;
		while (gx < 5) {
			if (Green[gx][y] != 0 || Green[gx + 1][y] != 0)
				break;
			gx++;
		}
		gx--;
		Green[gx][y] = 1;
		Green[gx + 1][y] = 1;
	}
}

void blueBlock(int t,int x) {
	//1*1
	if (t == 1) {
		int gy = 0;
		while (gy < 6) {
			if (Blue[x][gy] != 0)
				break;
			gy++;
		}
		gy--;
		Blue[x][gy] = 1;
	}
	//1*2
	else if (t == 2) {
		int gy = 0;
		while (gy < 5) {
			if (Blue[x][gy] != 0 || Blue[x][gy + 1] != 0)
				break;
			gy++;
		}
		gy--;
		Blue[x][gy] = 1;
		Blue[x][gy + 1] = 1;
	}
	//2*1
	else if (t == 3) {
		int gy = 0;
		while (gy < 6) {
			if (Blue[x][gy] != 0 || Blue[x + 1][gy] != 0)
				break;
			gy++;
		}
		gy--;
		Blue[x][gy] = 1;
		Blue[x + 1][gy] = 1;
	}
}

//초록색보드에서 타일로 가득 찬 행 찾기
int greenFull() {
	bool go_next = false;
	for (int i = 0; i < 6; i++) {
		go_next = false;
		for (int j = 0; j < 4; j++) {
			if (Green[i][j] == 0) {
				go_next = true;
				break;
			}
		}
		if(go_next==false)
			return i;
	}
	return -1;
}

int blueFull() {
	bool go_next = false;
	for (int i = 0; i < 6; i++) {
		go_next = false;
		for (int j = 0; j < 4; j++) {
			if (Blue[j][i] == 0) {
				go_next = true;
				break;
			}
		}
		if (go_next == false)
			return i;
	}
	return -1;
}

void greenRemove(int r) {
	for (int i = 0; i < 4; i++) {
		Green[r][i] = 0;
	}
	//밑으로 내리기
	for (int i = r - 1; i >= 0; i--) {
		for (int j = 0; j < 4; j++) {
			Green[i + 1][j] = Green[i][j];
		}
	}
}

void blueRemove(int c) {
	for (int i = 0; i < 4; i++) {
		Blue[i][c] = 0;
	}
	//밑으로 내리기
	for (int i = c - 1; i >= 0; i--) {
		for (int j = 0; j < 4; j++) {
			Blue[j][i + 1] = Blue[j][i];
		}
	}
}

//초록색 보드의 연한 칸에 블록이 있는지
int greenSpecial() {
	int cnt = 0;
	for (int i = 0; i <= 1; i++) {
		for (int j = 0; j < 4; j++) {
			if (Green[i][j] == 1) {
				cnt++;
				break;
			}
		}
	}
	return cnt;
}

//파란색 보드의 연한 칸에 블록이 있는지
int blueSpecial() {
	int cnt = 0;
	for (int i = 0; i <= 1; i++) {
		for (int j = 0; j < 4; j++) {
			if (Blue[j][i] == 1) {
				cnt++;
				break;
			}
		}
	}
	return cnt;
}

void putBlock() {
	for (int i = 0; i < N; i++) {
		int t = Block[i].t;
		int x = Block[i].x;
		int y = Block[i].y;
		//초록색 보드에 블럭 내리기
		greenBlock(t, y);
		//파란색 보드에 블럭 내리기
		blueBlock(t, x);
		while (1) {
			//초록색 보드에서 행이 가득 찬 경우가 없을 때까지 점수 획득
			while (1) {
				int r = greenFull();
				//꽉 찬 행이 없으면
				if (r == -1)
					break;
				score++;
				greenRemove(r);
			}
			//초록색 보드의 연한 칸에 블록이 있는지
			int cnt = greenSpecial();
			if (cnt == 0)
				break;
			for (int row = 5 - cnt; row >= 0; row--) {
				for (int col = 0; col < 4; col++) {
					Green[row + cnt][col] = Green[row][col];
					Green[row][col] = 0; 
				}
			}
		}
		//파란색 보드
		while (1) {
			//파란색 보드에서 행이 가득 찬 경우가 없을 때까지 점수 획득
			while (1) {
				int c = blueFull();
				//꽉 찬 열이 없으면
				if (c == -1)
					break;
				score++;
				blueRemove(c);
			}
			//파란색 보드의 연한 칸에 블록이 있는지
			int cnt = blueSpecial();
			if (cnt == 0)
				break;
			for (int col = 5 - cnt; col >= 0; col--) {
				for (int row = 0; row < 4; row++) {
					Blue[row][col + cnt] = Blue[row][col];
					Blue[row][col] = 0;
				}
			}
		}
	}
}

int main() {
	ios_base::sync_with_stdio(0);
	cin.tie(NULL);
	cout.tie(NULL);
	cin >> N;
	int t, x, y;
	for (int i = 0; i < N; i++) {
		cin >> t >> x >> y;
		Block.push_back({ t,x,y });
	}
	putBlock();
	cout << score << '\n';
	int block_cnt = 0;
	for (int i = 0; i < 6; i++) {
		for (int j = 0; j < 4; j++) {
			if (Green[i][j] == 1)
				block_cnt++;
			if (Blue[j][i] == 1)
				block_cnt++;
		}
	}
	cout << block_cnt << '\n';
}