코딩테스트/Java

[JAVA] 백준 끝나지 않는 파티(플로이드워셜)

SK_MOUSE 2022. 2. 14. 23:16
단뱡향 노드로 모든 길에 대한 값이 들어가있는 문제에서 사용!
따라서 플로이드 워셜로 순차적으로 업데이트 해나가는 삼중for문 방식이 더 효율적인 것을 알 수 있었다.
사이에 끼는것이 맨위에 있다고 기억!!
(i -> j) vs ( ( i-> k) + ( k -> j) )

플로이드 워셜 문제로 풀어야 시간초과가 나지 않는 문제이다.

단뱡향 노드로 모든 길에 대한 값이 들어가있는 문제에서 사용!

플로이드워셜

시행착오

1. BFS로 각각의 케이스에 대해서 따로 최단거리를 구하려했다

=> 파티장의 크기 N(5 ≤ N ≤ 500) , 파티장의 번호, C(1 ≤ C ≤ 1,000,000,000) 이므로 BruteForce(N * N = 2500)로 한번에 모든 거리를 구해놓아야 한다는 것을 깨달았다.

2. 완전탐색(Brute-Force)으로 모든것을 탐색할때 BFS방식으로 탐색했다.

=> 이미 진행한 길에 대해서 추가적인 낭비 노드가 발생한다.

 

따라서 플로이드 워셜로 순차적으로 업데이트 해나가는 삼중for문 방식이 더 효율적인 것을 알 수 있었다.

import java.io.*; import java.util.*; public class Main { ​​​​static int N, M; ​​​​static int p[][]; ​​​​public static void main(String[] args) throws IOException { ​​​​​​​​BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); ​​​​​​​​StringTokenizer st = new StringTokenizer(br.readLine()); ​​​​​​​​StringBuilder sb = new StringBuilder(); ​​​​​​​​N = Integer.parseInt(st.nextToken()); ​​​​​​​​M = Integer.parseInt(st.nextToken()); ​​​​​​​​p = new int[N][N]; ​​​​​​​​for (int i = 0; i < N; i++) { ​​​​​​​​​​​​st = new StringTokenizer(br.readLine()); ​​​​​​​​​​​​for (int j = 0; j < N; j++) { ​​​​​​​​​​​​​​​​p[i][j] = Integer.parseInt(st.nextToken()); ​​​​​​​​​​​​} ​​​​​​​​} ​​​​​​​​/*for (int i = 0; i < N; i++) {//bruteforce for (int j = 0; j < N; j++) { p[i][j] = bfs(i,j,p[i][j]); } } */ ​​​​​​​​//플로이드워셜 ​​​​​​​​for (int k = 0; k <N; k++) { ​​​​​​​​​​​​for (int i = 0; i < N; i++) { ​​​​​​​​​​​​​​​​for (int j = 0; j <N; j++) { ​​​​​​​​​​​​​​​​​​​​p[i][j]= Math.min(p[i][j], p[i][k] + p[k][j]); ​​​​​​​​​​​​​​​​} ​​​​​​​​​​​​} ​​​​​​​​} ​​​​​​​​for (int i = 0; i < M; i++) { ​​​​​​​​​​​​st = new StringTokenizer(br.readLine()); ​​​​​​​​​​​​int a = Integer.parseInt(st.nextToken()) - 1; ​​​​​​​​​​​​int b = Integer.parseInt(st.nextToken()) - 1; ​​​​​​​​​​​​int c = Integer.parseInt(st.nextToken()); ​​​​​​​​​​​​boolean canGo = c >= p[a][b]; ​​​​​​​​​​​​if (canGo) sb.append("Enjoy other party").append('\n'); ​​​​​​​​​​​​else sb.append("Stay here").append('\n'); ​​​​​​​​} ​​​​​​​​System.out.print(sb.toString()); ​​​​} /* static class Node { int x, time; public Node(int x, int time) { this.x = x; this.time = time; } } private static int bfs(int a, int b, int c) { Queue<Node> q = new LinkedList<>(); q.add(new Node(a, 0)); int shortestTime = c; while (!q.isEmpty()) { Node n = q.poll(); if (n.time > c) continue; if (n.x == b) { shortestTime = Math.min(shortestTime, n.time); continue; } for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { if (i != n.x) q.add(new Node(i, n.time + p[n.x][i])); } } } return shortestTime; }*/ }

주석 처리된부분은 시간초과로 정답처리 되지않는 방식이다.

 

위 코드에서 봐야할 부분은 플로이드 워셜 알고리즘 부분이다.

//플로이드워셜 ​​​​​​​​for (int k = 0; k <N; k++) { ​​​​​​​​​​​​for (int i = 0; i < N; i++) { ​​​​​​​​​​​​​​​​for (int j = 0; j <N; j++) { ​​​​​​​​​​​​​​​​​​​​p[i][j]= Math.min(p[i][j], p[i][k] + p[k][j]); ​​​​​​​​​​​​​​​​} ​​​​​​​​​​​​} ​​​​​​​​}

k가 맨위 for문이다! 즉, 사이에 끼는것이 맨위에 있다고 기억!!

(i -> j) vs ( ( i-> k) + ( k -> j) )

 

반응형

'코딩테스트 > Java' 카테고리의 다른 글

[JAVA] 백준 적록색약  (0) 2022.02.26
[JAVA] 백준 그대, 그머가 되어  (0) 2022.02.25
[JAVA] 백준 수강신청  (0) 2022.02.09
[JAVA] 백준 감소하는 수  (0) 2022.02.06
[JAVA] 백준 과자 나눠주기  (0) 2022.02.02