문제 설명
https://www.acmicpc.net/problem/2583
크기가 M * N인 모눈종이가 있고, K개의 직사각형을 그릴 때, 직사각형 내부를 제외한 나머지 부분이 몇개인지, 그리고 각 영역의 넓이가 얼마인지 오름차순으로 구하기
문제 풀이법
모든 정점을 방문하는 문제이므로 bfs, dfs 모두 사용할 수 있다
모눈종이를 가리키는 배열 arr, 방문하였는지 확인하는 배열 visited가 필요하다
- k개의 직사각형을 입력받아서 각 직사각형의 내부에 해당하는 arr의 좌표값을 1로 입력
- 좌측 하단이 (0, 0)이므로 헷갈리기에 좌측 상단을 (0, 0)으로 생각하고 연산을 진행함
- 입력된 (x1, y1, x2, y2)를 (x1, n - y1, x2, n - y2)로 변경 (n과 m도 문제와는 다르게 n을 y축, m을 x축으로 변경)
- (0, 0)부터 visited[y][x]가 0이고, arr[y][x]가 0인 지점을 dfs, bfs를 돌린다
- 각 영역의 크기가 구해지면 vector에 값을 입력한 후, 오름차순으로 정렬한다
- 원하는 값을 출력하면 끝!
소스 코드
bfs
#include <iostream>
#include <utility>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
int arr[101][101] = { 0 };
int visited[101][101] = { 0 };
int dy[4] = { 1, 0, -1, 0};
int dx[4] = { 0, 1, 0, -1};
int n, m, k;
int bfs(int y, int x)
{
visited[y][x] = 1;
queue<pair<int, int>> q;
q.push({y, x});
int cnt = 0;
while (!q.empty())
{
int yy = q.front().first;
int xx = q.front().second;
q.pop();
cnt++;
for (int i = 0; i < 4; i++)
{
int ny = yy + dy[i];
int nx = xx + dx[i];
if (ny < 0 || nx < 0 || ny >= n || nx >= m || visited[ny][nx] == 1 || arr[ny][nx] == 1)
continue;
q.push({ny, nx});
visited[ny][nx] = 1;
}
}
return (cnt);
}
int main()
{
cin >> n >> m >> k;
for (int i = 0; i < k; i++)
{
int x1, y1, x2, y2, tmp;
cin >> x1 >> y1 >> x2 >> y2;
y1 = n - y1;
y2 = n - y2;
if (y1 > y2)
{
tmp = y1;
y1 = y2;
y2 = tmp;
}
if (x1 > x2)
{
tmp = x1;
x1 = x2;
x2 = tmp;
}
for (int j = y1; j < y2; j++)
{
for (int p = x1; p < x2; p++)
arr[j][p] = 1;
}
}
vector<int> v;
int cnt = 0;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
if (arr[i][j] == 0 && visited[i][j] == 0)
{
int tmp = bfs(i, j);
v.push_back(tmp);
cnt++;
}
}
}
sort(v.begin(), v.end());
printf("%d\n", cnt);
for (int i = 0; i < v.size(); i++)
printf("%d ", v[i]);
return 0;
}
dfs
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int arr[101][101] = { 0 };
int visited[101][101] = { 0 };
int dy[4] = { 1, 0, -1, 0};
int dx[4] = { 0, 1, 0, -1};
int n, m, k;
int sum;
void dfs(int y, int x)
{
if (visited[y][x] == 1)
return ;
visited[y][x] = 1;
sum++;
for (int i = 0; i < 4; i++)
{
int ny = y + dy[i];
int nx = x + dx[i];
if (ny < 0 || nx < 0 || ny >= n || nx >= m || visited[ny][nx] == 1 || arr[ny][nx] == 1)
continue;
dfs(ny, nx);
}
}
int main()
{
cin >> n >> m >> k;
for (int i = 0; i < k; i++)
{
int x1, y1, x2, y2, tmp;
cin >> x1 >> y1 >> x2 >> y2;
y1 = n - y1;
y2 = n - y2;
if (y1 > y2)
{
tmp = y1;
y1 = y2;
y2 = tmp;
}
if (x1 > x2)
{
tmp = x1;
x1 = x2;
x2 = tmp;
}
for (int j = y1; j < y2; j++)
{
for (int p = x1; p < x2; p++)
arr[j][p] = 1;
}
}
vector<int> v;
int cnt = 0;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
if (arr[i][j] == 0 && visited[i][j] == 0)
{
sum = 0;
dfs(i, j);
v.push_back(sum);
cnt++;
}
}
}
sort(v.begin(), v.end());
printf("%d\n", cnt);
for (int i = 0; i < v.size(); i++)
printf("%d ", v[i]);
return 0;
}
'Algorithm Study' 카테고리의 다른 글
[백준] 12851 숨바꼭질 2 (0) | 2023.03.10 |
---|---|
[백준] 1697 숨바꼭질 (0) | 2023.03.10 |
[백준] 7569 토마토 (0) | 2023.03.06 |
[백준] 7576 토마토 (0) | 2023.03.06 |
[백준] 2178 미로 탐색 (0) | 2023.03.06 |