https://www.acmicpc.net/problem/14502
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
int dy[4] = {-1, 1, 0, 0};
int dx[4] = {0, 0, -1, 1};
int arr[8][8];
int sim[8][8];
bool visit[8][8];
int n, m;
int ans = 0;
vector<pair<int, int>> virus;
void initSim(){
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
sim[i][j] = arr[i][j];
visit[i][j] = false;
}
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin >> n >> m;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cin >> arr[i][j];
sim[i][j] = arr[i][j];
if (arr[i][j] == 2) {
virus.push_back(make_pair(i, j));
}
}
}
for (int i = 0; i < n * m - 2; i++) {
for (int j = i + 1; j < n * m - 1; j++) {
for (int k = j + 1; k < n * m; k++) {
initSim();
int wall = 0;
if (sim[i / m][i % m] == 0) {
sim[i / m][i % m] = 1;
wall++;
}
if (sim[j / m][j % m] == 0) {
sim[j / m][j % m] = 1;
wall++;
}
if (sim[k / m][k % m] == 0) {
sim[k / m][k % m] = 1;
wall++;
}
if (wall == 3) {
queue<pair<int, int>> q;
for (int vi = 0; vi < virus.size(); vi++) {
q.push(virus[vi]);
}
while (!q.empty()) {
pair<int, int> cur = q.front();
q.pop();
for (int dir = 0; dir < 4; dir++) {
int ny = cur.first + dy[dir];
int nx = cur.second + dx[dir];
if (ny >= 0 && ny < n && nx >= 0 && nx < m) {
if (!visit[ny][nx] && sim[ny][nx] == 0) {
visit[ny][nx] = true;
sim[ny][nx] = 2;
q.push(make_pair(ny, nx));
}
}
}
}
int cnt = 0;
for (int w = 0; w < n; w++) {
for (int h = 0; h < m; h++) {
if (sim[w][h] == 0) {
cnt++;
}
}
}
ans = max(ans, cnt);
}
}
}
}
cout << ans;
return 0;
}
1. 문제
n*m개의 연구소 현황이 주어진다. 0은 빈 공간, 1은 벽, 2는 바이러스이다. 이 연구소의 빈 공간중 정확히 3개를 골라 벽을 설치하려 한다. 이후 바이러스가 퍼지는데, 바이러스는 상하좌우의 빈 공간에 퍼진다. 다 퍼진 후 빈 공간을 안전 공간이라 칭하고, 이 넓이를 최대로 하려 할 때, 그 넓이를 출력하라.
2. 풀이
정확히 3개의 벽을 임의의 공간에 설치하고, 공간은 최대 8*8이므로 브루트포스를 이용하여 풀 수 있다.
int arr[8][8];
int sim[8][8];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cin >> arr[i][j];
sim[i][j] = arr[i][j];
if (arr[i][j] == 2) {
virus.push_back(make_pair(i, j));
}
}
}
연구소 현황을 입력받는다. 처음 연구소 현황을 유지해야 하므로 sim이라는 배열을 만든다. 이 배열에 벽을 설치하고, 바이러스를 퍼뜨릴 것이다. 바이러스를 퍼뜨릴 위치가 필요하므로 저장해준다.
for (int i = 0; i < n * m - 2; i++) {
for (int j = i + 1; j < n * m - 1; j++) {
for (int k = j + 1; k < n * m; k++) {
initSim();
int wall = 0;
if (sim[i / m][i % m] == 0) {
sim[i / m][i % m] = 1;
wall++;
}
if (sim[j / m][j % m] == 0) {
sim[j / m][j % m] = 1;
wall++;
}
if (sim[k / m][k % m] == 0) {
sim[k / m][k % m] = 1;
wall++;
}
이후 모든 연구소를 돌며 3개의 빈공간을 찾는다면 벽을 세운다.
,
if (wall == 3) {
queue<pair<int, int>> q;
for (int vi = 0; vi < virus.size(); vi++) {
q.push(virus[vi]);
}
while (!q.empty()) {
pair<int, int> cur = q.front();
q.pop();
for (int dir = 0; dir < 4; dir++) {
int ny = cur.first + dy[dir];
int nx = cur.second + dx[dir];
if (ny >= 0 && ny < n && nx >= 0 && nx < m) {
if (!visit[ny][nx] && sim[ny][nx] == 0) {
visit[ny][nx] = true;
sim[ny][nx] = 2;
q.push(make_pair(ny, nx));
}
}
}
벽이 3개라면 각 바이러스의 시작점에 대해 BFS를 돌린다. 다음 위치가 방문하지 않은 빈 공간일 경우 해당 위치에 바이러스를 퍼뜨리고, 다음 탐색위치로 저장해준다.
int cnt = 0;
for (int w = 0; w < n; w++) {
for (int h = 0; h < m; h++) {
if (sim[w][h] == 0) {
cnt++;
}
}
}
ans = max(ans, cnt);
모든 바이러스를 퍼뜨린 후, 연구소를 순회하면서 빈 공간(안전 공간)의 개수를 세어주고, 그 최댓값을 갱신해준다.
연산이 끝나고 ans를 출력하면 정답을 구할 수 있다.
'Coding Test' 카테고리의 다른 글
백준 2573 빙산 (C++) (0) | 2024.08.22 |
---|---|
백준 2812 크게 만들기 (C++) (1) | 2024.08.20 |
백준 2668 숫자고르기 (C++) (0) | 2024.08.17 |
Leetcode 624 Maximum Distance in Arrays (C++) (0) | 2024.08.16 |
백준 2696 중앙값 구하기 (C++) (0) | 2024.08.13 |