문제 링크: https://www.acmicpc.net/problem/2583
눈금의 간격이 1인 M×N(M,N≤100)크기의 모눈종이가 있다. 이 모눈종이 위에 눈금에 맞추어 K개의 직사각형을 그릴 때, 이들 K개의 직사각형의 내부를 제외한 나머지 부분이 몇 개의 분리된 영역으로 나누어진다.
예를 들어 M=5, N=7 인 모눈종이 위에 <그림 1>과 같이 직사각형 3개를 그렸다면, 그 나머지 영역은 <그림 2>와 같이 3개의 분리된 영역으로 나누어지게 된다.

M, N과 K 그리고 K개의 직사각형의 좌표가 주어질 때, K개의 직사각형 내부를 제외한 나머지 부분이 몇 개의 분리된 영역으로 나누어지는지, 그리고 분리된 각 영역의 넓이가 얼마인지를 구하여 이를 출력하는 프로그램을 작성하시오.
첫째 줄에 M과 N, 그리고 K가 빈칸을 사이에 두고 차례로 주어진다. M, N, K는 모두 100 이하의 자연수이다. 둘째 줄부터 K개의 줄에는 한 줄에 하나씩 직사각형의 왼쪽 아래 꼭짓점의 x, y좌표값과 오른쪽 위 꼭짓점의 x, y좌표값이 빈칸을 사이에 두고 차례로 주어진다. 모눈종이의 왼쪽 아래 꼭짓점의 좌표는 (0,0)이고, 오른쪽 위 꼭짓점의 좌표는(N,M)이다. 입력되는 K개의 직사각형들이 모눈종이 전체를 채우는 경우는 없다.
첫째 줄에 분리되어 나누어지는 영역의 개수를 출력한다. 둘째 줄에는 각 영역의 넓이를 오름차순으로 정렬하여 빈칸을 사이에 두고 출력한다.
문제가 사각형을 주어줬다. 하지만, 사각형으로 하면 문제가 좀 복잡해지고 어려워진다. 그래서 나는 사각형 대신 좌표하나가 한 사각형이라고 생각을 하고 문제를 풀었다. 문제를 풀 때는 전혀 문제가 되지 않는다.
모눈종이에서 사각형이 있지 않은 부분 중 사각형에 의해 나눠져있는 곳들의 개수와 크기를 구하는 문제이다.
- 입력
- 사각형이 있는 부분을 1로 표시해주기
- search 시작 전 0인 부분을 찾으면, count + 1 해주기.
- 0으로 표시된 부분을 dfs를 이용하여, search를 진행하고 search한 부분은 1로 표시.
- search하면서 자신의 branch를 다 체크했다면, size + 1 해준다.
- 자신이 속해 있는 sub-graph의 dfs를 다 진행했다면, size를 vector에 넣어주기.
- 위 과정이 다 끝나면, vector를 오름차순으로 sort해주기.
- 출력
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int X, Y, rectNum;
int map[101][101];
int xCheck[4] = {-1,0,0,1};
int yCheck[4] = {0,-1,1,0};
int cnt;
int rectSize;
vector<int> rectSizes;
void makeRect(int x1, int y1, int x2, int y2){
for(int i = y1 ; i < y2 ; i++){
for(int j = x1 ; j < x2 ; j++){
map[i][j] = 1;
}
}
}
void search(int x, int y){
int nextX, nextY;
for(int i = 0 ; i < 4 ; i++){
nextX = x + xCheck[i]; nextY = y + yCheck[i];
if(nextX >= 0 && nextX < X && nextY >= 0 && nextY < Y && map[nextY][nextX] == 0){
map[nextY][nextX] = 1;
search(nextX, nextY);
}
}
rectSize++;
}
void dfs(){
for(int i = 0 ; i < Y ; i++){
for(int j = 0 ; j < X ; j++){
if(map[i][j] == 0){
cnt++;
map[i][j] = 1;
search(j,i);
rectSizes.push_back(rectSize);
rectSize = 0;
}
}
}
}
int main(){
ios_base::sync_with_stdio(false);
cin.tie(NULL);cout.tie(NULL);
cin >> Y >> X >> rectNum;
int x1, x2, y1, y2;
for(int i = 0 ; i < rectNum ; i++){
cin >> x1 >> y1 >> x2 >> y2;
makeRect(x1, y1, x2, y2);
}
cnt = 0;
dfs();
sort(rectSizes.begin(), rectSizes.end());
cout << cnt << "\n";
for(int i = 0 ; i < rectSizes.size() ; i++){
cout << rectSizes[i] << " ";
}
cout << "\n";
}
문제를 꼭 주어진 대로만 풀면 복잡해지는 경우가 있다. 문제를 단순화 시킬 수 있다면 단순화 시켜서 문제를 다르게 접근하는 것도 하나의 방법인 것 같다.
이 문제 넘 어려워요ㅠ
코드 작성할 때 ‘’’C++
//code
‘’’로 감싸주시면 색이 입혀집니다!