📌 문제 링크 - https://www.acmicpc.net/problem/23035
문제
가톨릭대학교에는 많은 고양이가 있다. 고양이를 사랑하는 많은 학생 중 한 명인 쿠기는 수업 시간보다 항상 일찍 등교해서 고양이 밥을 챙겨주곤 했다. 안타깝게도 이제 4학년이 된 쿠기는 취업 준비에 바빠 고양이를 챙기는 것에 많은 시간을 쏟을 수 없게 되었다.
그런데도 고양이를 사랑하는 쿠기는 학교 정문에서부터 수업이 있는 다솔관까지 가는 여러 경로 중에, 가장 많은 고양이를 만나 밥을 챙겨 줄 수 있는 경로를 찾고 싶어 한다. 쿠기는 다솔관까지 상, 하, 좌, 우 방향으로만 이동하며, 한 번 이동하는 시간은 1만큼 걸린다. 이때, 고양이에게 밥을 주는 시간은 무시할 수 있을 정도로 짧다. 쿠기는 정문에서 다솔관까지 가장 빠르게 움직일 때만 수업에 늦지 않을 수 있다. 마음 착한 쿠기가 수업에 늦지 않으면서 최대한 많은 고양이의 밥을 챙길 수 있도록 도와주자.
가톨릭대는 크기가 N × M인 직사각형이고, 정문은 (0, 0), 다솔관은 (N, M)에 있다.
입력
첫 번째 줄에 정수 N, M(0 ≤ N, M ≤ 1,000,000,000)이 주어진다.
두 번째 줄에 고양이의 수를 나타내는 정수 T(0 ≤ T ≤ 100,000)가 주어진다.
세 번째 줄부터 T개의 줄에 고양이의 위치를 나타내는 정수 r, c(0 ≤ r, c ≤ 1,000,000,000)가 주어진다. 두 개 이상의 좌표가 중복되는 경우는 없고, 가톨릭대 밖에 고양이가 존재할 수 있다.
출력
첫 번째 줄에 수업 시간 전에 밥을 챙겨줄 수 있는 고양이의 최대 마릿수를 출력한다.
풀이
LIS를 응용해서 풀 수 있는 문제다.
가톨릭대 밖에 고양이가 존재할 수 있으므로 가톨릭대 크기인 N이나 M 이내의 위치만 리스트에 저장하였다.
입력을 받은 후 정렬을 해주면 되는데, 수업에 늦지 않기 위해 최소한의 이동으로 이동하면서 고양이의 밥을 챙겨주어야 하므로 현재 위치에서 이동할 때 반드시 오른쪽이나 아래쪽으로 가야 한다.
따라서 고양이의 위치를 r 좌표를 기준으로 오름차순 정렬해 준다. (r 좌표가 동일하다면 c 좌표를 기준으로 정렬해 준다.)
이후 r 좌표를 기준으로 고양이들의 위치를 정렬했으므로 c 좌표에 대해 LIS를 구해주면 된다.
기본 LIS 문제만 풀어봤었는데 응용문제를 풀면서 감을 잡을 수 있어서 좋은 문제였다. ㅎㅎ
코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.StringTokenizer;
// https://www.acmicpc.net/problem/23035
public class Main_23035 {
private static int N, M; // 가톨릭대 크기
private static List<Position> positions; // 고양이의 위치
public static void main(String[] args) throws IOException {
init();
int max = getMax();
System.out.print(max);
}//main
private static int getMax() {
int total = positions.size(); // 가톨릭대 안에 있는 고양이들 수
int cnt = 0; // 밥을 챙겨줄 수 있는 고양이의 최대 마릿수
int idx, curC;
int[] dp = new int[total + 1]; // c 좌표 저장
for(Position position : positions) {
curC = position.c; // 현재 고양이 위치
// 수업에 늦지 않고 갈 수 있는 위치에 고양이가 있다면
if (curC >= dp[cnt]) {
dp[++cnt] = curC;
continue;
}
idx = getIndex(curC, cnt, dp);
dp[idx] = curC;
}
return cnt;
}//getMax
private static int getIndex(int cur, int end, int[] dp) {
int start = 0;
int mid;
while(start < end) {
mid = (start + end) / 2;
if(dp[mid] > cur) end = mid;
else start = mid + 1;
}
return end;
}//getIndex
private static void init() throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 가톨릭대 크기
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
// 고양이의 수를 나타내는 정수가 주어진다.
int K = Integer.parseInt(br.readLine());
positions = new ArrayList<>(K); // 고양이의 위치
// 고양이의 위치를 나타내는 정수 r, c가 주어진다.
for(int i=0; i<K; i++) {
st = new StringTokenizer(br.readLine());
int r = Integer.parseInt(st.nextToken());
int c = Integer.parseInt(st.nextToken());
// 가톨릭대 밖에 고양이가 존재할 수 있다.
if(r > N || c > M) continue;
positions.add(new Position(r, c));
}
// 정렬
Collections.sort(positions);
br.close();
}//init
private static class Position implements Comparable<Position> {
int r;
int c;
public Position(int r, int c) {
this.r = r;
this.c = c;
}
@Override
public int compareTo(Position o) {
if(this.r == o.r) return this.c - o.c;
return this.r - o.r;
}
@Override
public String toString() {
return "r=" + r + ", c=" + c + '}';
}
}//Position
}//class
'Algorithm > 백준' 카테고리의 다른 글
[Java] 백준 2758. 로또 (0) | 2025.03.10 |
---|---|
[JAVA] 백준 4198. 열차정렬 (0) | 2025.02.20 |
[Java] 백준 22254. 공정 컨설턴트 호석 (1) | 2025.02.06 |
[Java] 백준 2343. 기타 레슨 (0) | 2025.01.30 |
[Java] 백준 17266. 어두운 굴다리 (0) | 2025.01.24 |