어흥

[백준 20061] 모노미노도미노 2 (C++) 본문

알고리즘/백준

[백준 20061] 모노미노도미노 2 (C++)

라이언납시오 2021. 3. 3. 18:03
728x90
반응형

문제 링크: www.acmicpc.net/problem/20061

 

20061번: 모노미노도미노 2

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

www.acmicpc.net

1. 주의할 점

- 모든 절차에 따른 함수를 정확히 구현해야 한다

- 연한색에 위치함으로 인해 사라지는 열/행은 점수에 반영되지 않는다

 

2. 구현

- 입력에 대해 블록을 V 벡터에 구조체 형태로 저장한다

- MV(0) ->Pop_down() -> MV(1) -> Pop_right() 함수가 한 사이클이다

- MV(0)을 통해 V에 저장된 형태의 블록을 아래로 내려서 Arr[][] 배열에 저장한다

- Pop_down() 함수를 통해 한 행에 4개가 쌓여 있는지 확인하며, 쌓여있다면 쌓인 행만큼 Result에 더하고 내린다. 이후, 연한색에 블록이 있는지 확인하며 있으면 차지하는 행만큼 위에서 아래로 내린다

- MV(1)을 통해 V에 저장된 형태의 블록을 오른쪽으로 움직여서 Arr[][] 배열에 저장한다

- Pop_right() 함수를 통해 한 열에 4개가 쌓여 있는지 확인하며, 쌓여있다면 쌓인 열만큼 Result에 더하고 오른쪽으로 민다. 이후, 연한색에 블록이 있는지 확인하며 있으면 차지하는 오른쪽으로 민다

- Cal() 함수를 통해 몇개의 블록이 남아있는지 확인한다

//이전 코드
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct info {
	int y, x;
};
info tmp;
bool arr[13][13];
vector<info> v;
int dx[2] = { 0,1 };        //아래,오른쪽으로 이동
int dy[2] = { 1,0 };
int result = 0;       //얻은 점수

int cal() {
	int cnt = 0;
	for (int i = 6; i < 10; i++)
		for (int j = 0; j < 4; j++)
			if (arr[i][j]) cnt++;
	for (int x = 6; x < 10; x++)
		for (int y = 0; y < 4; y++)
			if (arr[y][x]) cnt++;
	return cnt;
}

void pop_right() {
	int cnt = 0, idx = 9;
	for (int x = 9; x >= 6; x--) {
		bool canPop = true;
		for (int y = 0; y < 4; y++) {
			if (!arr[y][x]) {
				canPop = false;
				break;
			}
		}
		if (canPop) {
			idx = min(idx, x);
			cnt++;
			for (int y = 0; y < 4; y++)
				arr[y][x] = false;
		}
	}
	if (cnt) {
		for (int x = idx - 1; x >= 4; x--) {
			for (int y = 0; y < 4; y++) {
				arr[y][x + cnt] = arr[y][x];
				arr[y][x] = false;
			}
		}
	}
	result += cnt;
	cnt = 0;
	for (int x = 4; x <= 5; x++) {
		bool avail = false;
		for (int y = 0; y < 4; y++) {
			if (arr[y][x]) {
				avail = true;
				break;
			}
		}
		if (avail) cnt++;
	}
	if (cnt) {
		for (int x = 9; x >= 4; x--) {
			for (int y = 0; y < 4; y++) {
				arr[y][x + cnt] = arr[y][x];
				arr[y][x] = false;
			}
		}
	}
}

void pop_down() {
	int cnt = 0, idx = 9;
	for (int y = 9; y >= 6; y--) {
		bool canPop = true;
		for (int x = 0; x < 4; x++) {
			if (!arr[y][x]) {
				canPop = false;
				break;
			}
		}
		if (canPop) {
			idx = min(idx, y);
			cnt++;
			for (int x = 0; x < 4; x++)
				arr[y][x] = false;
		}
	}
	if (cnt) {        //삭제할 행이 존재한다면
		for (int y = idx - 1; y >= 4; y--) {
			for (int x = 0; x < 4; x++) {
				arr[y + cnt][x] = arr[y][x];
				arr[y][x] = false;
			}
		}
	}
	result += cnt;
	cnt = 0;
	for (int y = 4; y <= 5; y++) {
		bool avail = false;
		for (int x = 0; x < 4; x++) {
			if (arr[y][x]) {
				avail = true;
				break;
			}
		}
		if (avail) cnt++;
	}
	if (cnt) {
		for (int y = 9; y >= 4; y--) {
			for (int x = 0; x < 4; x++) {
				arr[y + cnt][x] = arr[y][x];
				arr[y][x] = false;
			}
		}
	}
}

void mv(int dir) {
	int m_len = 9;
	for (int k = 0; k < v.size(); k++) {
		int cx = v[k].x;
		int cy = v[k].y;
		int len = 0;
		while (1) {
			cy += dy[dir];
			cx += dx[dir];
			len++;
			if (cx == 10 || cy == 10 || arr[cy][cx]) {
				len--;
				break;
			}
		}
		m_len = min(m_len, len);
	}
	for (int k = 0; k < v.size(); k++) {
		int cx = v[k].x + dx[dir] * m_len;
		int cy = v[k].y + dy[dir] * m_len;
		arr[cy][cx] = true;
	}
	if (dir == 0) pop_down();
	else pop_right();
}

int main() {
	ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
	int query, order, x, y;
	cin >> query;
	for (int t = 0; t < query; t++) {
		cin >> order >> y >> x;
		v.clear();
		v.push_back({ y,x });
		if (order == 2)    v.push_back({ y,x + 1 });
		else if (order == 3)   v.push_back({ y + 1,x });
		mv(0);
		mv(1);
	}
    cout << result << '\n' << cal();
	return 0;
}


//최근 코드 - 2021.04.22
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct info {
	int y, x;
};
info tmp;
bool arr[11][11] = { false, };
int num, t, x, y, result = 0, tot = 0;
vector<info> v;
//하,우
int dx[2] = { 0,1 };
int dy[2] = { 1,0 };

void cal() {
	for (int i = 0; i < 10; i++)
		for (int j = 0; j < 10; j++)
			if (arr[i][j])
				tot++;
}

void goDown(int start, int mini, int cnt){
	for (int i = start; i >= mini + cnt; i--) {
		for (int j = 0; j < 4; j++) {
			arr[i][j] = arr[i - cnt][j];
		}
	}
	for (int i = mini; i < mini + cnt; i++)
		for (int j = 0; j < 4; j++)
			arr[i][j] = false;
}

void goRight(int start, int mini, int cnt) {
	for (int j = start; j >= mini + cnt; j--) {
		for (int i = 0; i < 4; i++) {
			arr[i][j] = arr[i][j - cnt];
		}
	}
	for (int j = mini; j < mini + cnt; j++)
		for (int i = 0; i < 4; i++)
			arr[i][j] = false;
}

void blur() {
	//아래
	int cnt = 0;
	for (int i = 4; i < 6; i++) {
		bool block = false;
		for (int k = 0; k < 4; k++) {
			if (arr[i][k]) {
				block = true;
				break;
			}
		}
		if (block) cnt++;
	}
	if (cnt) goDown(9, 4, cnt);

	//우
	cnt = 0;
	for (int j = 4; j < 6; j++) {
		bool block = false;
		for (int k = 0; k < 4; k++) {
			if (arr[k][j]) {
				block = true;
				break;
			}
		}
		if (block) cnt++;
	}
	if (cnt) goRight(9, 4, cnt);
}

void rmv() {
	//아래
	int cnt = 0, idx;
	for (int i = 6; i <10; i++) {
		int allFilled = true;
		for (int j = 0; j < 4; j++) {
			if (!arr[i][j]) {
				allFilled = false;
				break;
			}
		}
		if (allFilled) {
			cnt++;
			idx = i;
		}
	}
	if (cnt) {
		goDown(idx, 4, cnt);
		result += cnt;
	}
	cnt = 0;
	for (int j = 6; j < 10; j++) {
		int allFilled = true;
		for (int i = 0; i < 4; i++) {
			if (!arr[i][j]) {
				allFilled = false;
				break;
			}
		}
		if (allFilled) {
			cnt++;
			idx = j;
		}
	}
	if (cnt) {
		goRight(idx, 4, cnt);
		result += cnt;
	}
}

void mv() {
	for (int cd = 0; cd < 2; cd++) {
		int lowest = 11;
		for (int k = 0; k < v.size(); k++) {
			int cy = v[k].y;
			int cx = v[k].x;
			int i = 0;		//내려갈 수 있는 칸 수
			while (++i) {
				cy += dy[cd];
				cx += dx[cd];
				if (arr[cy][cx]) {
					lowest = min(lowest, i - 1);
					break;
				}
			}
		}
		for (int k = 0; k < v.size(); k++) {
			int ny = v[k].y + (dy[cd] * lowest);
			int nx = v[k].x + (dx[cd] * lowest);
			arr[ny][nx] = true;
		}
	}
}

int main() {
	ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
	cin >> num;
	for (int i = 0; i < 4; i++) {
		arr[10][i] = true;
		arr[i][10] = true;
	}
	for (int i = 0; i < num; i++) {
		cin >> t >> y >> x;
		v.clear();
		v.push_back({ y,x });
		if (t == 2) v.push_back({ y,x + 1 });
		else if (t == 3) v.push_back({ y + 1,x });
		mv();
		rmv();
		blur();
	}
	cal();
	cout << result << '\n' << tot;
	return 0;
}
728x90
반응형

'알고리즘 > 백준' 카테고리의 다른 글

[백준 15809] 전국시대 (C++)  (0) 2021.03.11
[백준 2922] 즐거운 단어 (C++)  (0) 2021.03.09
[백준 1561] 놀이 공원 (C++)  (3) 2021.02.25
[백준 3745] 오름세 (C++)  (0) 2021.02.25
[백준 3649] 로봇 프로젝트 (C++)  (0) 2021.02.25
Comments