https://www.acmicpc.net/problem/11067
11067번: 모노톤길
입력 데이터는 표준입력을 사용한다. 입력은 T개의 테스트 데이터로 구성된다. 입력의 첫 번째 줄에는 테스트 데이터의 개수 T가 정수로 주어진다. 각 테스트 데이터의 첫 번째 줄에는 카페의 수
www.acmicpc.net
![](https://blog.kakaocdn.net/dn/H9Cdy/btr0DVydkcM/CnbaxEjy059OYFX0WLsueK/img.png)
![](https://blog.kakaocdn.net/dn/Y3BHs/btr0AM2PdwS/6PQjSoGs4BcUffW3nwPyX0/img.png)
![](https://blog.kakaocdn.net/dn/byRw4e/btr0HuUqvlr/yC68QiB38oUaZeADjz5LY0/img.png)
풀이
제한 시간이 5초로 엄청 길고, n의 범위가 최대 100,000 이므로 T의 값에 따라서 완전 탐색도 충분히 가능하다고 본다.
문제 조건에는 "x축의 값이 작아지는 경우는 없어도 출구까지 도달할 수 있다." 이다.
따라서 카페 방문 순서는 아래와 같다.
1. 현재 위치와 같은 x축에 있는 카페들 중 가까운 카페부터 방문한다.
2. 현재 위치와 같은 x축의 카페를 모두 방문했다면 y축이 동일한 카페들 중 가장 가까운 카페를 방문한다.
위와 같은 순서로 카페를 방문하려면 x축의 값을 오름차순으로 정렬해주고, x축이 같은 것들끼리 y축을 정렬해줘야된다.
y축을 정렬할 때는 오름차순, 내림차순은 상관이 없다.
public int compareTo (Pos o) {
if (this.x > o.x) {
return 1;
} else if (this.x == o.x) {
return this.y > o.y ? 1 : -1;
} else {
return -1;
}
}
정렬을 끝낸 후에 첫번째 인덱스부터 차례대로 x, y축을 비교해준다. 체크해주는 과정에서 중요한 건 예시처럼 바로 오른쪽 방향으로 가는 게 아니라 위, 아래 방향으로 갔을 때 y축 값을 정렬했더라도 0에서 어떤 카페가 가장 가까운지 판단할 수 없기 때문에 시작값을 (-1, 0) 넣어줘야된다.
ArrayList<Pos> cafe = new ArrayList<>();
cafe.add(new Pos(-1, 0));
Collections.sort(cafe);
int idx = 1;
while (idx <= N) {
// x축이 같은 경우
if (cafe.get(idx).x == cafe.get(idx-1).x) {
idx++;
// y축이 같은 경우
} else if (cafe.get(idx).y == cafe.get(idx-1).y) {
idx++;
} else {
int cur = idx;
int curX = cafe.get(idx).x;
// x축이 같아질 때까지
while (idx <= N && curX == cafe.get(idx).x) {
idx++;
}
List<Pos> subList = cafe.subList(cur, idx);
Collections.reverse(subList);
}
}
위에서 x축을 오름차순으로 정렬했기 때문에 x축이 같다면 그냥 넘어가주면 된다.
![](https://blog.kakaocdn.net/dn/dQyDcG/btr0H7dCTYi/B3cOYDPKNdC4pSdHjJSnPK/img.png)
y축을 내림차순으로 정렬했다면 1번 y축과 같은 위로 올라갈 경우에 문제가 생길 것이고, 오름차순으로 정렬했다면 2번 y축과 같은 아래로 내려가는 경우에 문제가 생길 것이다.
문제가 생기는 이 부분을 찾아내서 subList를 이용해 reverse 시켜줘야된다.
<최종코드>
import java.io.*;
import java.util.*;
public class Main {
public static class Pos implements Comparable<Pos>{
int x, y;
public Pos (int x, int y) {
this.x = x;
this.y = y;
}
public int compareTo (Pos o) {
if (this.x > o.x) {
return 1;
} else if (this.x == o.x) {
return this.y > o.y ? 1 : -1;
} else {
return -1;
}
}
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
int T = Integer.parseInt(br.readLine()); // 테스트 케이스
for (int i=0; i<T; i++) {
int N = Integer.parseInt(br.readLine()); // 카페 개수
ArrayList<Pos> cafe = new ArrayList<>();
cafe.add(new Pos(-1, 0));
for (int j=0; j<N; j++) {
st = new StringTokenizer(br.readLine());
int x = Integer.parseInt(st.nextToken());
int y = Integer.parseInt(st.nextToken());
cafe.add(new Pos(x, y));
}
Collections.sort(cafe);
int idx = 1;
while (idx <= N) {
// x축이 같은 경우
if (cafe.get(idx).x == cafe.get(idx-1).x) {
idx++;
// y축이 같은 경우
} else if (cafe.get(idx).y == cafe.get(idx-1).y) {
idx++;
} else {
int cur = idx;
int curX = cafe.get(idx).x;
// x축이 같아질 때까지
while (idx <= N && curX == cafe.get(idx).x) {
idx++;
}
List<Pos> subList = cafe.subList(cur, idx);
Collections.reverse(subList);
}
}
st = new StringTokenizer(br.readLine());
int M = Integer.parseInt(st.nextToken());
for (int d=0; d<M; d++) {
int tmp = Integer.parseInt(st.nextToken());
System.out.println(cafe.get(tmp).x + " " + cafe.get(tmp).y);
}
}
}
}
'알고리즘 > 구현 & 그리디 & 브루트포스' 카테고리의 다른 글
[백준]JAVA - 10431번: 줄세우기 (0) | 2023.03.22 |
---|---|
[백준]JAVA - 1244번: 스위치 켜고 끄기 (0) | 2023.03.15 |
[백준]JAVA - 14503번: 로봇 청소기 (0) | 2023.02.16 |
[백준]JAVA - 7568번: 덩치 (0) | 2023.02.07 |
[백준]JAVA - 2116번: 주사위 쌓기 (0) | 2023.01.31 |