Skip to content

Commit 5e12465

Browse files
committed
[Week10] PGS_87694: 아이템 줍기
1 parent db37669 commit 5e12465

File tree

1 file changed

+97
-0
lines changed

1 file changed

+97
-0
lines changed
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package study.week10;
2+
3+
4+
import java.util.LinkedList;
5+
import java.util.Queue;
6+
7+
// 아이템 줍기
8+
// BFS
9+
/**
10+
* 시간복잡도 : O(N*W*H)
11+
* ㄷ 자 처럼 공간 건너뛰는 문제를 해결하기 위해 모든 좌표(사각형, 시작점, 아이템위치) 를 전부 2배하였다.
12+
* 그러면 최소 차이나는 위치가 2가 되므로 공간 뛰어넘는 문제를 해결할 수 있다.
13+
* 또한 각 좌표마다 사각형의 테두리 유효를 보지 않고, 미리 테두리만 딴 map 배열을 두고 하는 것이 효율적
14+
* 사각형 내부면 2, 테두리면 1로 두는데, 테두리가 다른 사각형 내부일 수 있으므로 2는 1을 덮을 수 있지만, 1은 2를 덮지 못하게 한다.
15+
* 이렇게 map 을 구한 다음 bfs를 진행하면 된다. map 1인부분, 방문 안한지점, 최대 최소 범위를 벗어나지 않은 좌표를 조건으로 탐색한다.
16+
* 만약 start와 item 의 위치가 같다면 cnt/2 의 값을 리턴하면 정답(모든 좌표를 2배했기에 탐색 거리도 2배가 된다)
17+
*/
18+
public class PGS_87694 {
19+
static class Solution {
20+
static class Point{
21+
int x;
22+
int y;
23+
int cnt;
24+
25+
public Point(int x, int y, int cnt){
26+
this.x = x;
27+
this.y = y;
28+
this.cnt = cnt;
29+
}
30+
}
31+
32+
static int[] dx = {1,0,-1,0};
33+
static int[] dy= {0,1,0,-1};
34+
35+
public int solution(int[][] rectangle, int characterX, int characterY, int itemX, int itemY) {
36+
int answer = 0;
37+
// 2배로 범위를 잡고, 각 사각형 및 좌표를 2배씩 하는 이유는, ㄷ 자처럼 공간을 뛰어넘는 문제를 해결하기 위함이다.
38+
int[][] map = new int[102][102];
39+
40+
// 각 사각형들 순회하면서 map 만들기
41+
for(int[] rec: rectangle){
42+
int downX = rec[0] * 2;
43+
int downY = rec[1] * 2;
44+
int upX = rec[2] * 2;
45+
int upY = rec[3] * 2;
46+
47+
// 여기서 범위를 직사각형으로 가둬서 테두리 외부는 아에 가능성 x
48+
for (int x = downX; x <= upX; x++) {
49+
for (int y = downY; y <= upY; y++) {
50+
// 직사각형의 내부인 경우 2로 채움 (테두리가 덮어쓰지 못하도록)
51+
if (x > downX && x < upX && y > downY && y < upY) {
52+
map[x][y] = 2;
53+
}
54+
// 직사각형의 테두리인 경우, 다른 직사각형의 내부(2)가 아닐 때만 1로 채움
55+
// 만약 1번 직사각형의 테두리가, 다른 직사각형의 내부일 수도 있으므로 !=2 일때만 채움
56+
else if (map[x][y] != 2) {
57+
map[x][y] = 1;
58+
}
59+
}
60+
}
61+
}
62+
63+
return bfs(map, characterX * 2, characterY * 2, itemX * 2, itemY * 2);
64+
}
65+
66+
private static int bfs(int[][] map, int startX, int startY, int itemX, int itemY) {
67+
Queue<Point> q = new LinkedList<>();
68+
boolean[][] visited = new boolean[102][102];
69+
70+
q.add(new Point(startX, startY, 0));
71+
visited[startX][startY] = true;
72+
73+
while (!q.isEmpty()) {
74+
Point now = q.poll();
75+
76+
// 아이템 위치에 도달하면, 거리를 2배로 뻥튀기 했었으므로 다시 2로 나누어 반환
77+
if (now.x == itemX && now.y == itemY) {
78+
return now.cnt / 2;
79+
}
80+
81+
for (int i = 0; i < 4; i++) {
82+
int nx = now.x + dx[i];
83+
int ny = now.y + dy[i];
84+
85+
// 맵 범위를 벗어나지 않고, 방문한 적 없으며, 테두리(1)인 곳만 이동
86+
if (nx >= 0 && nx <= 100 && ny >= 0 && ny <= 100) {
87+
if (!visited[nx][ny] && map[nx][ny] == 1) {
88+
visited[nx][ny] = true;
89+
q.offer(new Point(nx, ny, now.cnt + 1));
90+
}
91+
}
92+
}
93+
}
94+
return 0;
95+
}
96+
}
97+
}

0 commit comments

Comments
 (0)