백준/일반 문제

[백준/BOJ] 21609 - 상어 중학교 (c++)

sem; 2022. 4. 7. 14:10
반응형

https://www.acmicpc.net/problem/21609

 

BFS를 곁들인 구현문제였다...

 

저는 문제를 잘 못읽어서 다 풀어놓고도 몇분 헤맸던 문제였어요

 

이 문제는 문제에 써있는 순서대로

 

블럭그룹을 찾고,

블럭그룹을 지우고,

중력을 작용하고,

90도 반시계회전하고,

중력을 작용하는것을

 

함수를 짜서 순서대로 돌아가도록 하면 되는 문제였다.

 

주의할점으로는

  • 첫번째, 기준블럭을 정하는 규칙과 블럭그룹을 정하는 규칙을 정확히 이해해야한다.

처음에 이것을 잘못 이해해서 몇분 헤맸습니다..ㅠㅠ

 

  • 두번째, 무지개색깔 블럭을 검은블럭을 뺀 나머지 색깔블럭들도 접근할 수 있도록 해야한다.

저는 무지개색깔을 어떤 색깔이 접근을 했다면 다시 초기화하여 다른 색깔도 접근을 할 수 있도록 작성했습니다


소스코드

 

#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
#include <algorithm>
#define pii pair<int,int>

using namespace std;

struct bg {
	int r, c, cnt, rb;
};

int N, M, map[20][20], ans;
struct bg BG;

int dx[4] = { 0,0,1,-1 }, dy[4] = { 1,-1,0,0 };

void Input() {
	cin >> N >> M;
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			cin >> map[i][j];
		}
	}
}

void rainbowVisitClear(int visit[][20]) {
	for (int m = 0; m < N; m++) {
		for (int n = 0; n < N; n++) {
			if (map[m][n] == 0) visit[m][n] = 0;
		}
	}
}

bool isBigger(struct bg t, struct bg b) {
	if (t.cnt > b.cnt) return true;
	else if (t.cnt == b.cnt) {
		if (t.rb > b.rb) return true;
		else if (t.rb == b.rb) {
			if (t.r > b.r) return true;
			else if (t.r == b.r) {
				if (t.c > b.c) return true;
			}
		}
	}
	return false;
}

void getBG() {
	
	BG = { -1,-1,-1,-1 };
	int visit[20][20];
	queue<int> qx, qy;

	memset(visit, 0, sizeof(visit));

	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {

			if (visit[i][j] || map[i][j] < 1) continue;

			rainbowVisitClear(visit);

			struct bg tmp = { 0,0,0,0 };
			tmp.r = i, tmp.c = j, tmp.cnt = 0;
			qx.push(i), qy.push(j);
			visit[i][j] = 1;

			while (!qx.empty()) {
				int cx = qx.front(), cy = qy.front();
				qx.pop(), qy.pop();
				tmp.cnt++;
				if (map[cx][cy] == 0) tmp.rb++;

				for (int k = 0; k < 4; k++) {
					int nx = cx + dx[k], ny = cy + dy[k];
					if (nx < 0 || ny < 0 || nx >= N || ny >= N || visit[nx][ny]) continue;

					if (map[nx][ny] == 0 || map[nx][ny] == map[i][j]) {
						qx.push(nx), qy.push(ny);
						visit[nx][ny] = 1;
						if (map[nx][ny] == map[i][j]) {
							if (tmp.r > nx) tmp.r = nx, tmp.c = ny;
							else if (tmp.r == nx && tmp.c > ny) tmp.r = nx, tmp.c = ny;
						}
					}
				}
			}

			if (tmp.cnt > 1) {
				if (isBigger(tmp, BG)) BG = tmp;
			}
		}
	}
}

void removeBG() {
	int visit[20][20], BGcolor = map[BG.r][BG.c];
	queue<int> qx, qy;

	ans += BG.cnt * BG.cnt;
	memset(visit, 0, sizeof(visit));
	qx.push(BG.r), qy.push(BG.c);

	while (!qx.empty()) {
		int cx = qx.front(), cy = qy.front();
		qx.pop(), qy.pop();

		map[cx][cy] = -2;

		for (int i = 0; i < 4; i++) {
			int nx = cx + dx[i], ny = cy + dy[i];
			if (nx < 0 || ny < 0 || nx >= N || ny >= N || visit[nx][ny]) continue;

			if (map[nx][ny] == 0 || map[nx][ny] == BGcolor) {
				qx.push(nx), qy.push(ny);
				visit[nx][ny] = 1;
			}
		}
	}
}

void gravity() {
	for (int i = N - 1; i >= 0; i--) {
		for (int j = 0; j < N; j++) {
			if (map[i][j] >= 0) {
				int nx = i;
				while (true) {
					if (nx + 1 >= N || map[nx + 1][j] >= -1) break;
					nx++;
				}
				int tmp = map[i][j];
				map[i][j] = -2;
				map[nx][j] = tmp;
			}
		}
	}
}

void turn() {
	int tmp[20][20];
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			tmp[i][j] = map[j][N - 1 - i];
		}
	}
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			map[i][j] = tmp[i][j];
		}
	}
}

void Solution() {
	while (true) {
		getBG();
		if (BG.r == -1) break;

		removeBG();
		gravity();
		turn();
		gravity();
	}
	cout << ans;
}

int main() {
	Input();
	Solution();
}
반응형