[BOJ] 16958 : 텔레포트

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