Skip to content

Commit 772ef8e

Browse files
authored
[BOJ] 영역구하기 / 실버1 / 40분
[BOJ] 영역구하기 / 실버1 / 40분
2 parents 21603c5 + cac05e6 commit 772ef8e

2 files changed

Lines changed: 231 additions & 0 deletions

File tree

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import java.io.BufferedReader;
2+
import java.io.InputStreamReader;
3+
import java.util.PriorityQueue;
4+
import java.util.StringTokenizer;
5+
6+
public class BOJ_16236_아기상어 {
7+
8+
private static int N; // 공간 크기
9+
private static int[][] map; // 공간 저장 배열
10+
private static int[] start; // 탐색 시작 위치 저장 배열
11+
private static boolean[][] visited; // 방문여부 저장
12+
private static int size; // 아기상어 크기
13+
private static int sec; // 물고기를 잡아먹을 수 있는 시간
14+
private static int cnt; // 물고기 개수
15+
private static int bite; // 물고기를 잡아먹은 횟수
16+
private static int[] end; // 물고기를 잡아먹은 지점
17+
18+
// 탐색 방향
19+
private static int[] dx = {1, 0, -1, 0};
20+
private static int[] dy = {0, 1, 0, -1};
21+
22+
// 다익스트라 탐색
23+
private static int bfs(int x, int y) {
24+
PriorityQueue<int[]> q = new PriorityQueue<>((a, b) -> {
25+
if (a[2] != b[2]) return Integer.compare(a[2], b[2]); // 거리 비교
26+
if (a[0] != b[0]) return Integer.compare(a[0], b[0]); // 행 비교
27+
return Integer.compare(a[1], b[1]); // 열 비교
28+
});
29+
30+
visited[x][y] = true;
31+
q.offer(new int[] {x, y, 0});
32+
33+
while(!q.isEmpty()) {
34+
int[] cur = q.poll();
35+
int cx = cur[0];
36+
int cy = cur[1];
37+
int dist = cur[2];
38+
39+
// 물고기를 잡아 먹었다면 종료지점 저장 후, 거리 반환
40+
if (map[cx][cy] != 0 && map[cx][cy] < size) {
41+
end[0] = cx;
42+
end[1] = cy;
43+
return dist;
44+
}
45+
46+
for (int i = 0; i < 4; i++) {
47+
int nx = cx + dx[i];
48+
int ny = cy + dy[i];
49+
50+
if (nx < 0 || nx >= N || ny < 0 || ny >= N) continue; // 범위 체크
51+
if (visited[nx][ny] || size < map[nx][ny]) continue; // 방문 여부, 더 큰 물고기인지 체크
52+
53+
visited[nx][ny] = true;
54+
q.offer(new int[] {nx, ny, dist + 1});
55+
}
56+
}
57+
58+
return -1; // 잡아먹을 물고기가 없으면 -1 반환
59+
}
60+
61+
62+
public static void main(String[] args) throws Exception {
63+
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
64+
65+
N = Integer.parseInt(br.readLine());
66+
67+
map = new int[N][N];
68+
start = new int[2];
69+
size = 2;
70+
sec = 0;
71+
cnt = 0;
72+
bite = 0;
73+
end = new int[2];
74+
75+
for (int i = 0; i < N; i++) {
76+
StringTokenizer st = new StringTokenizer(br.readLine());
77+
for (int j = 0; j < N; j++) {
78+
map[i][j] = Integer.parseInt(st.nextToken());
79+
// 탐색 시작 위치 저장
80+
if (map[i][j] == 9) {
81+
start[0] = i;
82+
start[1] = j;
83+
map[i][j] = 0; // 위치 저장 후, 0으로 초기화
84+
}
85+
// 잡아먹을 수 있는 물고기 있는지 체크
86+
if (map[i][j] != 0 && map[i][j] != 9) cnt++;
87+
}
88+
}
89+
90+
// 잡아 먹을 수 있는 물고기가 있는지 먼저 체크 후 없다면 0 반환
91+
if (cnt == 0) {
92+
System.out.println(0);
93+
return;
94+
}
95+
96+
while (true) {
97+
visited = new boolean[N][N]; // 방문여부 배열 반복문마다 생성
98+
int move = bfs(start[0], start[1]); // 시작 지점부터 탐색
99+
100+
if (move == -1) break; // 더 이상 잡아먹을 물고기 없으면 반복문 종료
101+
102+
map[end[0]][end[1]] = 0; // 잡아먹은 물고기 위치 0으로 초기화
103+
104+
bite++; // 물고기를 잡아먹은 횟수 증가
105+
if (size == bite) { // 크기와 잡아먹은 횟수가 같아지면
106+
size++; // 크기 증가
107+
bite = 0; // 잡아먹은 횟수 초기화
108+
}
109+
110+
sec += move; // 이동거리만큼 시간 증가
111+
112+
// 탐색 종료 지점을 시작 위치로 설정
113+
start[0] = end[0];
114+
start[1] = end[1];
115+
}
116+
117+
System.out.println(sec);
118+
}
119+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import java.io.BufferedReader;
2+
import java.io.InputStreamReader;
3+
import java.util.ArrayDeque;
4+
import java.util.ArrayList;
5+
import java.util.Collections;
6+
import java.util.List;
7+
import java.util.Queue;
8+
import java.util.StringTokenizer;
9+
10+
public class BOJ_2583_영역구하기 {
11+
12+
private static int M; // 종이 세로 크기
13+
private static int N; // 종이 가로 크기
14+
private static int K; // 직사각형 개수
15+
private static int[][] paper; // 종이 저장 배열
16+
private static List<Integer> list; // 분리된 영역 넓이 저장 리스트
17+
private static boolean[][] visited; // 방문여부 저장 배열
18+
19+
// 탐색 방향
20+
private static int[] dx = {1, 0, -1, 0};
21+
private static int[] dy = {0, 1, 0, -1};
22+
23+
// 분리된 영역 구하는 메서드
24+
private static int bfs(int x, int y) {
25+
Queue<int[]> q = new ArrayDeque<>();
26+
27+
visited[x][y] = true;
28+
q.offer(new int[] {x, y});
29+
30+
int cnt = 1; // 분리된 영역의 넓이
31+
32+
while(!q.isEmpty()) {
33+
int[] cur = q.poll();
34+
int cx = cur[0];
35+
int cy = cur[1];
36+
37+
for (int i = 0; i < 4; i++) {
38+
int nx = cx + dx[i];
39+
int ny = cy + dy[i];
40+
41+
if (nx < 0 || nx >= M || ny < 0 || ny >= N) continue; // 범위체크
42+
if (visited[nx][ny] || paper[nx][ny] == 1) continue; // 방문여부, 직사각형 여부 체크
43+
44+
visited[nx][ny] = true;
45+
q.offer(new int[] {nx, ny});
46+
cnt++;
47+
}
48+
}
49+
50+
return cnt;
51+
}
52+
53+
public static void main(String[] args) throws Exception {
54+
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
55+
StringBuilder sb = new StringBuilder();
56+
57+
StringTokenizer st = new StringTokenizer(br.readLine());
58+
M = Integer.parseInt(st.nextToken());
59+
N = Integer.parseInt(st.nextToken());
60+
K = Integer.parseInt(st.nextToken());
61+
62+
paper = new int[M][N];
63+
list = new ArrayList<>();
64+
visited = new boolean[M][N];
65+
66+
for (int i = 0; i < K; i++) {
67+
st = new StringTokenizer(br.readLine());
68+
int x1 = Integer.parseInt(st.nextToken());
69+
int y1 = Integer.parseInt(st.nextToken());
70+
int x2 = Integer.parseInt(st.nextToken());
71+
int y2 = Integer.parseInt(st.nextToken());
72+
73+
// 자꾸 아웃오브인덱스 나길래 확인해보니
74+
// y좌표를 먼저 돌려줘야 하네요ㅠㅠ.
75+
// 기본적으로 생각해야하는데, 아직 y, x 좌표가 헷갈릴 때가 있습니다.
76+
// for (int x = x1; x < x2; x++) {
77+
// for (int y = y1; y < y2; y++) {
78+
// paper[x][y] = 1;
79+
// }
80+
// }
81+
82+
// 직사각형 영역은 1로 바꿔주기
83+
for (int y = y1; y < y2; y++) {
84+
for (int x = x1; x < x2; x++) {
85+
paper[y][x] = 1;
86+
}
87+
}
88+
}
89+
90+
// 분리된 영역 구하기
91+
int cnt = 0; // 분리된 영역 개수
92+
for (int i = 0; i < M; i++) {
93+
for (int j = 0; j < N; j++) {
94+
if (paper[i][j] != 1 && !visited[i][j]) {
95+
int area = bfs(i, j); // 분리된 영역 넓이
96+
list.add(area);
97+
cnt++;
98+
}
99+
}
100+
}
101+
102+
// 분리된 영역의 넓이 오름차순 정렬
103+
Collections.sort(list);
104+
105+
sb.append(cnt + "\n");
106+
for (int val : list) {
107+
sb.append(val + " ");
108+
}
109+
110+
System.out.println(sb);
111+
}
112+
}

0 commit comments

Comments
 (0)