[BOJ] 16958 : 텔레포트
풀이
시뮬레이션
한 도시A에서 B로 가는 방법은
A->B / A->가까운S->가까운S->B
두가지 중 하나로 요약할 수 있다.
A가 가까운S라면 거리가0으로 처리하면되고, B도 마찬가지이다.
맨처음에 A->B, B->A로 바로 가는 거리를 미리 구해놓은뒤,
S를 거쳐서 텔레포트해서 가는 최소거리를 갱신하면 정답이다.
코드
#include <algorithm>
#include <vector>
#include <cmath>
#include <string>
#include <iostream>
using namespace std;
int n, t;
int x[1000];
int y[1000];
int s[1000];
int arr[1000][1000];
int getDis(int i, int j) {
int t1 = abs(x[i] - x[j]);
int t2 = abs(y[i] - y[j]);
return t1 + t2;
}
//u에서 가장 가까운 거리의 s인곳의 좌표
//없으면 -1을 리턴.
int near(int u) {
int ans = -1;//거리
int w = -1; //좌표
for (int i = 0; i < n; i++) {
if (s[i] == 0)
continue;
if (ans == -1 || ans > arr[u][i]) {
ans = arr[u][i];
w = i;
}
}
return w;
}
int calc(int u, int v) {
int ans = arr[u][v];
//s가1인곳은 어짜피 near함수하면 자기자신이 리턴될것이다
int us = near(u);
int vs = near(v);
if (us == -1 || vs == -1)
return ans;
int tmp = arr[u][us] + t + arr[vs][v];
if (ans > tmp)
ans = tmp;
return ans;
}
int main() {
cin >> n >> t;
for (int i = 0; i < n; i++) {
cin >> s[i] >> x[i] >> y[i];
}
//arr 초기화
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n;j++)
arr[i][j] = arr[j][i] = getDis(i, j);
}
int m;
cin >> m;
while (m--) {
int u, v;
cin >> u >> v;
u--;
v--;
cout << calc(u, v) << '\n';
}
return 0;
}
Written on April 13, 2019