프로그래밍/PS

[C++] 백준 14502번: 연구소

유태정 2021. 1. 4. 16:24
반응형

첫 번째 시도

0인 칸 중 세 칸을 골라 1로 만드는 모든 경우를 저장한다.

그 경우를 모두 순회하며 2인 칸부터 시작하여 너비 우선 탐색을 진행한다.

인접한 칸이 0인 칸을 2로 만들어가며 너비우선탐색을 마치면,

0인 칸의 수를 세어 최대값을 찾는다.

더보기
#include <bits/stdc++.h>

using namespace std;

#define TC(T) int T; cin >> T; while(T--)
#define FAST_IO cin.tie(NULL); ios::sync_with_stdio(false);
#define FOR(i, N) for(int i = 0; i < N; ++i)
#define INF 987654321
#define ERR 1e-13
#define EL "\n"

int main() {
#ifdef DEBUG
	freopen("input.txt", "r", stdin);
	//	freopen("output.txt", "w", stdout);
#endif
	FAST_IO;

	int N, M;
	cin >> N >> M;

	vector<vector<int>> Lab(N, vector<int>(M));
	FOR(r, N) FOR(c, M)
		cin >> Lab[r][c];

	typedef pair<int, int> Vec2;
	
	// Collect all situation 0 to 1
	vector<Vec2> Emptys;
	FOR(r, N) FOR(c, M)
		if (Lab[r][c] == 0)
			Emptys.push_back(make_pair(r, c));
	vector<vector<Vec2>> Walls;
	const int SIZE = Emptys.size();
	for (int e0 = 0; e0 < SIZE; ++e0)
		for (int e1 = 0; e1 < SIZE; ++e1)
			for (int e2 = 0; e2 < SIZE; ++e2)
				Walls.push_back({ Emptys[e0], Emptys[e1], Emptys[e2] });

	// Explore the Lab from 2
	constexpr int adjs[4][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
	int max_safe_area = 0;
	for (auto& sit : Walls) {
		// Set the new walls
		auto Lab_ = Lab;
		for (auto& wall : sit)
			Lab_[wall.first][wall.second] = 1;

		// Add start point that is 2
		queue<Vec2> BFS;
		FOR(r, N) FOR(c, M)
			if (Lab[r][c] == 2)
				BFS.push(make_pair(r, c));
		
		// Explore the Lab_ from 2
		while (BFS.size()) {
			auto& [r, c] = BFS.front();

			for (auto& adj : adjs) {
				int chg_r = r + adj[0];
				int chg_c = c + adj[1];
				if (chg_r < 0 || chg_r >= N) continue;
				if (chg_c < 0 || chg_c >= M) continue;
				if (Lab_[chg_r][chg_c] != 0) continue;
				BFS.push(make_pair(chg_r, chg_c));
				Lab_[chg_r][chg_c] = 2;
			}

			BFS.pop();
		}

		// Count the safe area
		int safe_area = 0;
		FOR(r, N) FOR(c, M)
			if (Lab_[r][c] == 0)
				safe_area++;
		max_safe_area = max(max_safe_area, safe_area);
	}

	cout << max_safe_area << EL;

	return 0;
}

하지만 틀렸다. 예제는 모두 통과했다.

반례 찾기

8 8
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0

정답은 61이지만 63이 출력된다. 0에서 1로 세 칸을 바꾸는데, 그 세 칸이 모두 같은 경우가 있다는 뜻이다.

코드를 천천히 다시 살펴보니 오류가 있었다. 중첩 반복문에서 초기값이 0이 아니라 그 윗 단계의 +1을 한 값이 들어가야 한다.

vector<vector<Vec2>> Walls;
const int SIZE = Emptys.size();
for (int e0 = 0; e0 < SIZE; ++e0)
	for (int e1 = 0; e1 < SIZE; ++e1)
		for (int e2 = 0; e2 < SIZE; ++e2)
			Walls.push_back({ Emptys[e0], Emptys[e1], Emptys[e2] });
vector<vector<Vec2>> Walls;
const int SIZE = Emptys.size();
for (int e0 = 0; e0 < SIZE; ++e0)
	for (int e1 = e0 + 1; e1 < SIZE; ++e1)
		for (int e2 = e1 + 1; e2 < SIZE; ++e2)
			Walls.push_back({ Emptys[e0], Emptys[e1], Emptys[e2] });

코드

#include <bits/stdc++.h>

using namespace std;

#define TC(T) int T; cin >> T; while(T--)
#define FAST_IO cin.tie(NULL); ios::sync_with_stdio(false);
#define FOR(i, N) for(int i = 0; i < N; ++i)
#define INF 987654321
#define ERR 1e-13
#define EL "\n"

int main() {
#ifdef DEBUG
	freopen("input.txt", "r", stdin);
	//	freopen("output.txt", "w", stdout);
#endif
	FAST_IO;

	int N, M;
	cin >> N >> M;

	vector<vector<int>> Lab(N, vector<int>(M));
	FOR(r, N) FOR(c, M)
		cin >> Lab[r][c];

	typedef pair<int, int> Vec2;
	
	// Collect all situation 0 to 1
	vector<Vec2> Emptys;
	FOR(r, N) FOR(c, M)
		if (Lab[r][c] == 0)
			Emptys.push_back(make_pair(r, c));
	vector<vector<Vec2>> Walls;
	const int SIZE = Emptys.size();
	for (int e0 = 0; e0 < SIZE; ++e0)
		for (int e1 = e0 + 1; e1 < SIZE; ++e1)
			for (int e2 = e1 + 1; e2 < SIZE; ++e2)
				Walls.push_back({ Emptys[e0], Emptys[e1], Emptys[e2] });

	// Explore the Lab from 2
	constexpr int adjs[4][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
	int max_safe_area = 0;
	for (auto& sit : Walls) {
		// Set the new walls
		auto Lab_ = Lab;
		for (auto& wall : sit)
			Lab_[wall.first][wall.second] = 1;

		// Add start point that is 2
		queue<Vec2> BFS;
		FOR(r, N) FOR(c, M)
			if (Lab[r][c] == 2)
				BFS.push(make_pair(r, c));
		
		// Explore the Lab_ from 2
		while (BFS.size()) {
			auto& [r, c] = BFS.front();

			for (auto& adj : adjs) {
				int chg_r = r + adj[0];
				int chg_c = c + adj[1];
				if (chg_r < 0 || chg_r >= N) continue;
				if (chg_c < 0 || chg_c >= M) continue;
				if (Lab_[chg_r][chg_c] != 0) continue;
				BFS.push(make_pair(chg_r, chg_c));
				Lab_[chg_r][chg_c] = 2;
			}

			BFS.pop();
		}

		// Count the safe area
		int safe_area = 0;
		FOR(r, N)
			FOR(c, M)
				if (Lab_[r][c] == 0)
					safe_area++;
		max_safe_area = max(max_safe_area, safe_area);
	}

	cout << max_safe_area << EL;

	return 0;
}

제출 결과

반응형