https://www.acmicpc.net/problem/16958
플로이드 워셜을 이용하여 풀이할 수 있는 문제였다.
우선 좌표 정보와 특별한 도시 여부를 표현하기 위한 Point
클래스를 정의하였다.
이후 입력시 이 Point
클래스를 통해 도시 정보들을 List
에 저장하고 map
을
초기화하는 initMap
메서드에선 두 도시 에 대해 map[i][j]
를 다음과 같이 설정한다.
T
와 두 도시간 이동 시간중 작은 것을 map[i][j]
로 설정map[i][j]
로 설정이후, 플로이드 워셜을 통해 모든 도시간 최단 경로 비용을 구해 map
에 저장한뒤 주어지는
M
개의 쿼리에 답하면 된다.
로직의 시간복잡도는 플로이드 워셜의 으로 수렴하므로 최악의 경우 시간 초과가
떠야 맞지만 아마 언어에 따른 시간 보너스가 좀 여유롭게 주어진 유형인 것 같다.
찾아보니 보통 1초=1억(번의 연산)이 정론이나 단순 연산의 경우 1초=10억도 가능한 경우가
있다는 것 같다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import static java.lang.Integer.*;
public class Main {
static int N, T;
static int[][] map;
static List<Point> points = new ArrayList<>();
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = parseInt(st.nextToken());
T = parseInt(st.nextToken());
map = new int[N + 1][N + 1];
points.add(null);
int x, y, special;
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
special = parseInt(st.nextToken());
x = parseInt(st.nextToken());
y = parseInt(st.nextToken());
points.add(new Point(x, y, special == 1));
}
initMap();
floyd();
int M = parseInt(br.readLine());
int i, j;
StringBuilder sb = new StringBuilder();
while (M-- > 0) {
st = new StringTokenizer(br.readLine());
i = parseInt(st.nextToken());
j = parseInt(st.nextToken());
sb.append(map[i][j]).append("\n");
}
System.out.print(sb);
br.close();
}
static void initMap() {
Point p1, p2;
int d;
for (int i = 1; i < points.size() - 1; i++) {
p1 = points.get(i);
for (int j = i + 1; j < points.size(); j++) {
if (i == j) continue;
p2 = points.get(j);
d = Math.abs(p2.y - p1.y) + Math.abs(p2.x - p1.x);
if (p1.special && p2.special) {
map[i][j] = map[j][i] = Math.min(T, d);
} else {
map[i][j] = map[j][i] = d;
}
}
}
}
static void floyd() {
for (int k = 1; k <= N; k++)
for (int i = 1; i <= N; i++)
for (int j = 1; j <= N; j++) {
if (map[i][k] == MAX_VALUE || map[k][j] == MAX_VALUE)
continue;
map[i][j] = Math.min(map[i][j], map[i][k] + map[k][j]);
}
}
static class Point {
int x, y;
boolean special;
public Point(int x, int y, boolean special) {
this.x = x;
this.y = y;
this.special = special;
}
}
}