꾸물꾸물 졔의 개발공부
[백준] 1090 체커 - JAVA 본문
1090번: 체커
N개의 체커가 엄청 큰 보드 위에 있다. i번 체커는 (xi, yi)에 있다. 같은 칸에 여러 체커가 있을 수도 있다. 체커를 한 번 움직이는 것은 그 체커를 위, 왼쪽, 오른쪽, 아래 중의 한 방향으로 한 칸
www.acmicpc.net
알고리즘
N개의 체커가 주어질 때, 1≤k≤N인 k개의 체커가 같은 칸에 모이도록 이동하는 최소 횟수를 출력.
2차원 좌표에서 점들이 주어질 때 모든 점이 모일 수 있는 최선의 선택은 중간값을 찾는 것이다. (주어진 점들의)x좌표의 중간값, y좌표의 중간값을 찾으면 된다. ( 두개의 점이 주어졌을 때, 점간 거리는 |x-x1| + |y-y1| 로, x좌표와 y좌표가 독립적으로 계산되어 더해지기 떄문에 x좌표와 y좌표를 따로 구분지어 중간값을 찾아도 된다.)
모든 점들의 최선의 선택을 위해서는 주어진 좌표들 중 중간값을 찾으면 되지만, 문제에서는 임의의 k개가 모이는 최선의 선택을 각각 찾아내야 한다. 중간값(최선의 선택)을 어떤 점으로 하냐에 따라 이동횟수가 달라지기 때문에, 모든 중간값 후보들에 대해 완전탐색을 진행하여 k개를 모을 수 있는 최소 횟수를 구했다.
중간값 후보 ?
위에서 말했듯이 x좌표와 y좌표를 따로 구분지어 각각의 중간값을 찾으면 된다. 주어진 N개의 x좌표와, 주어진 N개의 y좌표를 기준으로 탐색하기 때문에 총 N^2개의 좌표를 탐색할 수 있다.예를들어, 예제 1번과 같은 경우에는
노란줄이 x좌표, 초록줄이 y좌표이기 때문에 초록색과 노란색이 겹치는 모든 점들 (9개) 이 중간값의 후보가 될 수 있다.
구현 알고리즘
1. 주어진 N개의 좌표들을 List에 넣는다.
2. ( 1≤k≤N ) k개의 점들을 모으기 위한 최소횟수를 저장할 배열 min을 생성하여, 최대 정수로 초기화한다.
3. N개의 좌표들의 x좌표, y좌표를 사용해서 N^2개의 중간값 후보들을 구한다. (이중 for문)
4. 중간값 (x,y) 가 주어졌을 때 아래 방법을 통해 최소 횟수를 찾아낸다.
- 우선순위큐 생성
- (x,y)에서 주어진 N개 좌표까지의 거리를 계산하여 큐에 삽입
- 우선순위큐에 의하여 거리가 짧은 것부터 저장
- 큐에서 하나씩 poll() 하며 sum에 더한다. sum과 min값을 비교하여 최소 횟수 갱신
소스 코드
import java.util.*;
public class Solution_BaekJoon_1090 {
private static List<int[]> list;
private static int min[];
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N= sc.nextInt(); //체커의 갯수
min = new int[N]; //체커가 같은 칸에 모일떄의 최소 갯수
Arrays.fill(min, Integer.MAX_VALUE);
list= new ArrayList<>();
while(N-->0) {
int x=sc.nextInt();
int y=sc.nextInt();
list.add(new int[] {x,y});
}
/*
* 범위 내에 있는 점들에 대해서 각 좌표까지의 거리
* 가장 가까운 k(1~n)개의 합 */
for(int i=0; i<list.size(); i++) {
int x = list.get(i)[0];
for(int j=0; j<list.size(); j++) {
int y = list.get(j)[1];
//중간값의 후보에 대해 모두 탐색
checkDis(x,y);
}
}
//1개가 모이는건 0 (자연수니까 무조건 1이상)
min[0]=0;
System.out.print(min[0]);
for(int i=1; i<min.length; i++) {
System.out.print(" "+min[i]);
}
}//end of main
/*
* (x,y)에서 각 좌표까지의 거리를 구해서, 가장 작은거 n개 더하기 */
private static void checkDis(int x, int y) {
PriorityQueue<Integer> que= new PriorityQueue<>();
for(int i=0; i<list.size(); i++) {
//주어져있었던 4개의 좌표들
int lx = list.get(i)[0];
int ly = list.get(i)[1];
que.add(calDis(x,y,lx,ly));
}
int sum = que.poll();
int index =1;
while(!que.isEmpty()) {
sum+=que.poll();
if(sum < min[index]) min[index] = sum;
index++;
}
}//end of checkDis
/*
* 현재 탐색 중인 점으로부터 각 좌표까지의 거리 계산 */
private static int calDis(int x, int y, int lx, int ly) {
return Math.abs(x-lx) + Math.abs(y-ly);
}
}//end of class
[ 중간값의 원리를 사용하는 비슷한 문제 ]
백준 14400 - 편의점 2 ( JAVA )
14400번: 편의점 2 영선이는 이번에 편의점으로 창업을 하려고 계획 중이다. 이번 창업을 위해 많은 준비를 하고 있는데, 아직 편의점을 세울 위치를 결정을 하지 못했다. 영선이는 미리 시장조사
jiko1456.tistory.com
백준 18310 - 안테나 ( JAVA )
18310번: 안테나 첫째 줄에 집의 수 N이 자연수로 주어진다. (1≤N≤200,000) 둘째 줄에 N채의 집에 위치가 공백을 기준으로 구분되어 1이상 100,000이하의 자연수로 주어진다. www.acmicpc.net 알고리즘 일
jiko1456.tistory.com
'알고리즘 > 백준' 카테고리의 다른 글
[백준] 16234 인구 이동 - JAVA (0) | 2023.03.17 |
---|---|
[백준] 4963 섬의 개수 - JAVA (0) | 2023.03.15 |
백준 18310 - 안테나 ( JAVA ) (0) | 2023.03.08 |
백준 14400 - 편의점 2 ( JAVA ) (0) | 2023.03.07 |
백준 1065 - 한수 ( JAVA ) (0) | 2023.03.02 |