Algorithm/최단거리

BOJ#1162 도로포장

밤이2209 2017. 3. 22. 13:09

BOJ#1162 도로포장


* 문제


* 풀이

그래프 최단거리를 찾는 문제로써, 다익스트라 알고리즘으로 문제를 풀 수 있습니다.

그러나 K개 이하로 도로 포장하여 가중치를 제거할 수 있기 때문에 추가적인 문제 풀이 방법이 요구됩니다.


따라서 기존의 dist 배열을 아래와 같이 바꿔봅시다.

-기존의 dist[i] : 시작점에서 i까지의 최단 경로 cost라고 한다면

-이 문제에서 dist[i][k] : 시작점에서 i까지 k개 도로를 포장하여 가는 최단 경로 cost


기존과 동일하게 dijkstra 알고리즘을 쓰되 각 경로에서 포장하는 경우, 포장하지 않는 경우를 구분하여 진행하면 되겠습니다.




* 나의 코드

https://github.com/stack07142/BOJ/blob/master/BOJ%231162_RevampingTrails/src/Main.java


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.StringTokenizer;

/**
* BOJ#1162 도로포장
* https://www.acmicpc.net/problem/1162
*/

public class Main {

static final int INF = 100000000;

public static void main(String[] args) throws IOException {

int N; // 도시의 수 1 <= N <= 10000
int M; // 도로의 수 1 <= M <= 50000
int K; // 포장할 도로의 수 1 <= K <= 20
ArrayList<ArrayList<Edge>> adj = new ArrayList<>();
int[][] dist; // dist[i][k] : 도로를 k개 포장 했을 때 1 -> N으로 가는 최소 cost

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());

N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
K = Integer.parseInt(st.nextToken());

dist = new int[N + 1][K + 1];

for (int i = 0; i < N + 1; i++) {

Arrays.fill(dist[i], INF);
adj.add(new ArrayList<>());
}

for (int i = 0; i < M; i++) {

st = new StringTokenizer(br.readLine());

int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
int w = Integer.parseInt(st.nextToken());

adj.get(a).add(new Edge(b, w));
adj.get(b).add(new Edge(a, w));
}

dijkstra(1, K, adj, dist);

int ans = INF;
for (int i = 0; i <= K; i++) {

ans = ans > dist[N][i] ? dist[N][i] : ans;
}

System.out.println(ans);

}

static void dijkstra(int src, int K, ArrayList<ArrayList<Edge>> adj, int[][] dist) {

PriorityQueue<Element> pq = new PriorityQueue<>();

dist[src][0] = 0;

pq.add(new Element(src, 0, dist[src][0]));

while (!pq.isEmpty()) {

int here = pq.peek().node;
int step = pq.peek().step;
int cost = pq.peek().dist;

pq.poll();

if (dist[here][step] < cost) {

continue;
}

for (Edge x : adj.get(here)) {

int adjNode = x.toNode;
int weight = x.cost;

// 도로 포장을 하는 경우
if (step + 1 <= K && dist[adjNode][step + 1] > dist[here][step]) {

dist[adjNode][step + 1] = dist[here][step];
pq.add(new Element(adjNode, step + 1, dist[adjNode][step + 1]));
}

// 도로 포장을 하지 않는 경우
if (dist[adjNode][step] > dist[here][step] + weight) {

dist[adjNode][step] = dist[here][step] + weight;
pq.add(new Element(adjNode, step, dist[adjNode][step]));
}
}
}
}
}

class Element implements Comparable<Element> {

int node;
int step;
int dist;

Element(int node, int step, int dist) {

this.node = node;
this.step = step;
this.dist = dist;
}

@Override
public int compareTo(Element o) {

return this.dist < o.dist ? -1 : 1;
}
}

class Edge {

int toNode;
int cost;

Edge(int toNode, int cost) {

this.toNode = toNode;
this.cost = cost;
}

@Override
public String toString() {

return "Edge(" + toNode + "," + cost + ")";
}
}


'Algorithm > 최단거리' 카테고리의 다른 글

BOJ#5214 환승  (0) 2017.03.31
BOJ#1261 알고스팟  (0) 2017.03.30
BOJ#1753 최단경로  (2) 2017.03.21
BOJ#1865 웜홀  (0) 2017.01.19
BOJ#11657 타임머신  (1) 2017.01.17