문제
유엔 화학 무기 조사단이 대량 살상 화학 무기를 만들기 위해 화학 물질들이 저장된 창고를 조사하게 되었다.
창고에는 화학 물질 용기 n2개가 n x n으로 배열되어 있었다.
유엔 조사단은 각 용기를 조사하여 2차원 배열에 그 정보를 저장하였다.
빈 용기에 해당하는 원소는 ‘0’으로 저장하고, 화학 물질이 들어 있는 용기에 해당하는 용기는 화학 물질의 종류에 따라 ‘1’에서 ‘9’사이의 정수를 저장하였다.
다음 그림은 창고의 화학 물질 현황을 9x9 배열에 저장한 예를 보여준다.
유엔 조사단은 화학 물질이 담긴 용기들로부터 3가지 사항을 발견하였다.
1. 화학 물질이 담긴 용기들이 사각형을 이루고 있다. 또한, 사각형 내부에는 빈 용기가 없다.
예를 들어, 위의 그림에는 3개의 화학 물질이 담긴 용기들로 이루어진 사각형 A, B, C가 있다.
2. 화학 물질이 담긴 용기들로 이루어진 사각형들은 각각 차원(가로의 용기 수 x 세로의 용기 수)이 다르다.
예를 들어, 위의 그림에서 A는 3x4, B는 2x3, C는 4x5이다.
3. 2개의 화학 물질이 담긴 용기들로 이루어진 사각형들 사이에는 빈 용기들이 있다.
예를 들어, 위의 그림에서 A와 B 사이와 B와 C 사이를 보면, 빈 용기를 나타내는 ‘0’ 원소들이 2개의 사각형 사이에 있는 것을 알 수 있다.
단, A와 C의 경우와 같이 대각선 상으로는 빈 용기가 없을 수도 있다.
유엔 조사단은 창고의 용기들에 대한 2차원 배열에서 행렬(화학 물질이 든 용기들로 이루어진 사각형)들을 찾아내고 정보를 수집하고자 한다.
찾아낸 행렬들의 정보를 출력하는 프로그램을 작성하시오.
[제약 사항]
n은 100 이하이다.
부분 행렬의 열의 개수는 서로 다르며 행렬의 행의 개수도 서로 다르다.
예를 들어, 3개의 부분행렬 행렬 (A(3x4), B(2x3), C(4x5))이 추출되었다면, 각 부분 행렬의 행의 수는 3, 2, 4로 서로 다르다.
마찬가지로 각 부분 행렬의 열의 수도 4, 3, 5로 서로 다르다.
테스트 케이스는 여러 개의 그룹으로 구성되며 아래와 같다.
그룹 1. n <= 10 이고 sub matrix의 개수 5개 이하
그룹 2. n <= 40 이고 5 < sub matrix <= 10
그룹 3. 40 < n <=80 이고 5 < sub matrix <= 10
그룹 4. 40 < n <=80 이고 10 < sub matrix <= 15
그룹 5. 80 < n<=100 이고 15 < sub matrix <= 20
풀이방법
BFS(너비 우선 탐색)으로 각 영역의 수를 찾는다. 2차원 배열이 주어졌을 때, 원소의 값이 0 보다 크면서 원소를 방문하지 않았다면
큐에 담고 탐색을 시작한다.
이 때, 큐에 맨 처음에 담았던 x1, y1 좌표와 큐에서 맨 마지막에 나온 x2, y2좌표를 저장하고,
클래스를 만들어, 영역마다 행의 길이(x2 - x1), 열의 길이(y2 - y1), 영역의 크기((x2 - x1) * (y2 - y1))를 저장한 객체를 생성한다.
영역의 크기 순으로 객체를 정렬하고, 행의 길이, 열의 길이, 크기를 출력한다.
소스코드
package samsung;
import java.util.*;
public class s_1258 {
static int[][] a;
static int n;
static int[][] v;
static int[] dx = {-1, 0, 1, 0};
static int[] dy = {0, 1, 0, -1};
static ArrayList <Ret> rets;
public static class Ret implements Comparable<Ret>{
int row;
int col;
int size;
Ret(int row, int col){
this.row = row + 1;
this.col = col + 1;
this.size = this.row * this.col;
}
@Override
public int compareTo(Ret r) {
if(this.size > r.size)
return 1;
else
return -1;
}
}
public static class Node{
int x;
int y;
Node(int x, int y){
this.x = x;
this.y = y;
}
}
public static void bfs(int x, int y) {
Queue <Node> q = new LinkedList<>();
v[x][y] = 1;
int start_x = x;
int start_y = y;
int end_x = x;
int end_y = y;
q.add(new Node(x, y));
while(!q.isEmpty()) {
Node node = q.poll();
x = node.x;
y = node.y;
end_x = x;
end_y = y;
for(int i = 0; i < 4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
if(nx >= 0 && ny >= 0 && nx < n && ny < n) {
if(a[nx][ny] > 0 && v[nx][ny] == 0) {
v[nx][ny] = 1;
q.add(new Node(nx,ny));
}
}
}
}
rets.add(new Ret(end_y - start_y, end_x - start_x));
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int tc = sc.nextInt();
for(int t = 1; t <= tc; t++) {
n = sc.nextInt();
a = new int[n+1][n+1];
v = new int[n+1][n+1];
rets = new ArrayList<>();
int cnt = 0;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) {
a[i][j] = sc.nextInt();
}
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) {
if(a[i][j] > 0 && v[i][j] == 0) {
cnt++;
bfs(i, j);
}
}
}
Collections.sort(rets);
System.out.print("#" + t + " " + cnt + " ");
for(int i = 0; i < rets.size(); i++) {
System.out.print(rets.get(i).col + " " + rets.get(i).row + " ");
}
System.out.println();
}
}
}
'Problem Solving > SWEA' 카테고리의 다른 글
[SWEA] 5432. 쇠막대기 자르기 (0) | 2020.03.09 |
---|---|
[SWEA] 1861. 정사각형 방 (0) | 2020.03.09 |
[SWEA] 1233. [S/W 문제해결 기본] 9일차 - 사칙연산 유효성 검사 (0) | 2020.03.09 |
[SWEA] 1232. [S/W 문제해결 기본] 9일차 - 사칙연산 (0) | 2020.03.07 |
[SWEA] 1231. [S/W 문제해결 기본] 9일차 - 중위순회 (0) | 2020.03.07 |
댓글