문제
방향성이 없는 그래프가 주어진다. 세준이는 1번 정점에서 N번 정점으로 최단 거리로 이동하려고 한다. 또한 세준이는 두 가지 조건을 만족하면서 이동하는 특정한 최단 경로를 구하고 싶은데, 그것은 바로 임의로 주어진 두 정점은 반드시 통과해야 한다는 것이다.

세준이는 한번 이동했던 정점은 물론, 한번 이동했던 간선도 다시 이동할 수 있다. 하지만 반드시 최단 경로로 이동해야 한다는 사실에 주의하라. 1번 정점에서 N번 정점으로 이동할 때, 주어진 두 정점을 반드시 거치면서 최단 경로로 이동하는 프로그램을 작성하시오.

입력
첫째 줄에 정점의 개수 N과 간선의 개수 E가 주어진다. (2 ≤ N ≤ 800, 0 ≤ E ≤ 200,000) 둘째 줄부터 E개의 줄에 걸쳐서 세 개의 정수 a, b, c가 주어지는데, a번 정점에서 b번 정점까지 양방향 길이 존재하며, 그 거리가 c라는 뜻이다. (1 ≤ c ≤ 1,000) 다음 줄에는 반드시 거쳐야 하는 두 개의 서로 다른 정점 번호가 주어진다.

출력
첫째 줄에 두 개의 정점을 지나는 최단 경로의 길이를 출력한다. 그러한 경로가 없을 때에는 -1을 출력한다.


예전에 막 짠 코드를 수정해 다시 짠 것. 다익스트라 알고리즘으로 풀었다.

다만 과정에서 중복된 연산을 여러 번 진행한 부분이 있다.


(result1, result2를 계산하는 부분에서 getDistance(1, mid1) 과 (1,mid2)는 함수를 한 번만 돌려서 모두 얻어낼 수 있고, 

(mid2, n) 과 (mid1, n)또한 마찬가지. (mid1, mid2)와 (mid2, mid1)또한 같은 값인데 여러 번 불러낸 것이 된다.) 


이 문제는 함수를 계속 부르는 것이 비효율이지만, 직관적으로는 이렇게 짜는 게 나을 것 같았다.

결과는 메모리 16M정도를 사용하여 330ms정도에 결과가 나왔다. 


LENGTH_MAX는 vertex갯수인 800과, 한 edge의 최댓값인 1000을 곱한 것이 거리의 최댓값이므로 800000을 최대로, 중간점이 2개이므로, 2400000을 MAX로 설정하였다. 물론 이 수가 작아서 충분히 크게 설정한 것이고, 실제로는 이 값보다 작은 값이 실제 최댓값으로 나오게 된다.

#include<iostream>
#include<queue>
#include<map>

const int LENGTH_MAX = 2400010;

using namespace std;

map<int, int> edge[800]; 					// adjacency list
int n, e;

int getDistance(int from, int to) {
	priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;		// save distance(result) in order of <distance, vertex>
	int dist[800];
	bool done[800];

	for (int i = 0; i < n; i++) {
		dist[i] = LENGTH_MAX;
		done[i] = false;
	}

	dist[from - 1] = 0;
	q.push(make_pair(0, from - 1));

	while (!q.empty()) {
		int cur_vert = q.top().second;
		int cur_dist = q.top().first;
		q.pop();
		if (done[cur_vert]) continue;
		done[cur_vert] = true;
		for (pair<const int, int> temp : edge[cur_vert]) { // temp.first : vertex index , temp.second : edge length
			if (temp.second + cur_dist < dist[temp.first]) {
				dist[temp.first] = temp.second + cur_dist;
				q.push(make_pair(dist[temp.first], temp.first));
			}
		}
	}

	return dist[to - 1];
}

int main() {

	int from, to, length, mid1, mid2;

	cin >> n >> e;

	for (int i = 0; i < e; i++) {
		cin >> from >> to >> length;
		if (edge[from - 1][to - 1] == 0 || length < edge[from - 1][to - 1]) {
			edge[from - 1][to - 1] = length;
			edge[to - 1][from - 1] = length;
		}
	}
	cin >> mid1 >> mid2;

	int result1 = getDistance(1, mid1) + getDistance(mid1, mid2) + getDistance(mid2, n);
	int result2 = getDistance(1, mid2) + getDistance(mid2, mid1) + getDistance(mid1, n);

	int result = result1 < result2 ? result1 : result2;
	if (result >= LENGTH_MAX) {
		cout << -1;
	}
	else {
		cout << result;
	}

	return 0;
}

새로 글을 쓰려다가 그냥 아래에 첨부하는 게 나을 것 같아 아래에 첨부.

필요없는 연산을 여러 번 하게 되는 코드여서 그 문제를 해결하기 위해 약간의 수정을 가했다.

원래의 코드를 대부분 재활용했으므로, 함수의 오버로딩에서 parameter가 바뀐 것, result1,2를 계산하는 부분 외에는 거의 같은 코드.

 

함수는 하나의 출발점에서 여러 목적지로 가는 거리를 재는 함수를 기본으로 구현했다.

목적지를 vector기반 으로 받는 것으로부터, array형으로 입력을 받거나, 하나의 목적지로 가는 것도 구현.

vector기반이어서 size를 사용하면 굳이 목적지의 갯수는 parameter로 받지 않아도 되지만, 입력값의 validity를 확인할 수 있을 것 같아 일단 받았다.

validity checking은 함수에 포함되어 있지 않다.


결과를 보니 메모리는 같은 양을 사용하고, 시간은 2/3로 줄었다.

어차피 함수를 부른 후에 메모리는 해제될 것이므로 메모리의 차이는 없는게 맞을 것이다.

연산 횟수에 있어서는, 기존엔 6번의 다익스트라 알고리즘을 수행하지만, 바꾼 코드에서는 3번만 수행하면 되기 때문에 이 정도 시간이 줄어든 것 같다.

아래는 수정한 코드.

#include<iostream>
#include<queue>
#include<map>
#include<vector>

const int LENGTH_MAX = 2400010;

using namespace std;

map<int, int> edge[800]; 					// adjacency list
int n, e;

vector<int> getDistance(int from, int numOfDestinations, vector<int> destinations) {
	vector<int> result;
	priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;		// save distance(result) in order of <distance, vertex>
	int dist[800];
	bool done[800];

	for (int i = 0; i < n; i++) {
		dist[i] = LENGTH_MAX;
		done[i] = false;
	}

	dist[from - 1] = 0;
	q.push(make_pair(0, from - 1));

	while (!q.empty()) {
		int cur_vert = q.top().second;
		int cur_dist = q.top().first;
		q.pop();
		if (done[cur_vert]) continue;
		done[cur_vert] = true;
		for (pair<const int, int> temp : edge[cur_vert]) { // temp.first : vertex index , temp.second : edge length
			if (temp.second + cur_dist < dist[temp.first]) {
				dist[temp.first] = temp.second + cur_dist;
				q.push(make_pair(dist[temp.first], temp.first));
			}
		}
	}
	for (int i = 0; i < numOfDestinations; i++) {
		result.push_back(dist[destinations[i] - 1]);
	}
	return result;
}

int getDistance(int from, int to) {
	vector<int> destinations = { to };
	return getDistance(from, 1, destinations)[0];
}

vector<int> getDistance(int from, int numOfDestinations, int destinations[]) {
	vector<int> des_vec;
	for (int i = 0; i < numOfDestinations; i++) {
		des_vec.push_back(destinations[i]);
	}
	return getDistance(from, numOfDestinations, des_vec);
}

int main() {
	int from, to, length, mid1, mid2;

	cin >> n >> e;

	for (int i = 0; i < e; i++) {
		cin >> from >> to >> length;
		if (edge[from - 1][to - 1] == 0 || length < edge[from - 1][to - 1]) {
			edge[from - 1][to - 1] = length;
			edge[to - 1][from - 1] = length;
		}
	}
	cin >> mid1 >> mid2;

	int result1, result2;
	
	//result1 = getDistance(1, mid1) + getDistance(mid1, mid2) + getDistance(mid2, n);
	//result2 = getDistance(1, mid2) + getDistance(mid2, mid1) + getDistance(mid1, n);

	vector<int> from1 = getDistance(1, 2, { mid1, mid2 }), fromN = getDistance(n, 2, { mid1, mid2 });
	int mid1Tomid2 = getDistance(mid1, mid2);

	result1 = from1[0] + mid1Tomid2 + fromN[1];
	result2 = from1[1] + mid1Tomid2 + fromN[0];

	int result = result1 < result2 ? result1 : result2;
	if (result >= LENGTH_MAX) {
		cout << -1;
	}
	else {
		cout << result;
	}

	return 0;
}


'Exercises > 길찾기' 카테고리의 다른 글

백준 1504  (1) 2018.05.06
1504 cpp  (0) 2018.05.05
백준 1504 수정  (0) 2018.05.05
백준 1504  (2) 2018.05.04
백준 문제 1504  (0) 2018.05.03

모든 루트를 최적화해서 길을 찾아야 한다고 생각해서 모든 시작점에서 끝점으로 가는 루트를 업데이트했었는데,

한 level씩 추가로 탐색하는 것으로도 모든 case를 탐색할 수 있다. (inductively생각하면~)

그러면 모든 시작점을 고려할 필요 없이 첫점->중간점1->중간점2->끝점 의 루트만 생각하면 되므로(중간점1과 2는 바뀔 수 있지만)

3개의 시작점 첫점, 중간1점, 중간2점 만 고려하면 되므로 최대 3/800정도의 시간단축이 생길 듯.

물론 각 첫점을 search하는 데는, 모든 점을 업데이트 하지 않으니까 더 많은 루프를 돌아 최적을 찾아야 하므로

약 50~100배의 향상이 있을 것 같다.

import java.util.Scanner;

public class Main {
	public int[] routeFrom(int startindex, int[][] route){
		int n=route.length;
		boolean changed=true;
		for(;changed;) {
			changed=false;
			for(int i=0;i<n;i++) {
				for(int j=0;j<n;j++) {
					if(route[startindex][i]!=0 && route[i][j]!=0 && 
						(route[startindex][j]>route[startindex][i]+route[i][j] || (route[startindex][j]==0 && startindex!=j))) {
						route[startindex][j]=route[startindex][i]+route[i][j];
						changed=true;
					}
//					System.out.printf("%d ", route[startindex][j]);
				}
//				System.out.println();
			}
//			System.out.println(startindex+"의 루프를 돌고 있습니다.");
		}
//		System.out.println("======================");
		return route[startindex];
	}
	
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		Main main=new Main();
		int N=sc.nextInt(), m=sc.nextInt();
		int[][] route=new int[N][N];
		for(int i=0;i<m;i++) {
			int from=sc.nextInt(), to=sc.nextInt(), distance=sc.nextInt(); // input route information
//			int from=(int)(Math.random()*N)+1, to=(int)(Math.random()*N)+1, distance=(int)(Math.random()*1000)+1; // input route information
			route[from-1][to-1]=distance;
			route[to-1][from-1]=distance;
		}
//		for(int i=0;i<N;i++) {
//			for(int j=0;j<N;j++) {
//				System.out.printf("%d ",route[i][j]);
//			}
//			System.out.println();
//		}
//		System.out.println("=====================");
		int mid1=sc.nextInt(), mid2=sc.nextInt();
//		int mid1=(int)(Math.random()*N)+1, mid2=(int)(Math.random()*N)+1;
		int[] routeFrom1=main.routeFrom(0,route);
		int[] routeFromMid1=main.routeFrom(mid1-1,route);
		int[] routeFromMid2=main.routeFrom(mid2-1,route);
		
		int startToMid1=routeFrom1[mid1-1];
		int mid1ToMid2=routeFromMid1[mid2-1];
		int mid2ToEnd=routeFromMid2[N-1];
		int startToMid2=routeFrom1[mid2-1];
		int mid2ToMid1=routeFromMid2[mid1-1];
		int mid1ToEnd=routeFromMid1[N-1];
		if(mid1==1 || mid1==N) {
			if(mid2==1 || mid2==N) {
				if(routeFrom1[N-1]==0) {
					System.out.println(-1);
				}
				else {
					System.out.println(routeFrom1[N-1]);
				}
			}
			else if(startToMid2==0 || mid2ToEnd==0){
				System.out.println(-1);
			}
			else {
				System.out.println(startToMid2+mid2ToEnd);
			}
		}
		else if(mid2==1 || mid2==N) {
			if(startToMid1==0 || mid1ToEnd==0) {
				System.out.println(-1);
			}
			else {
				System.out.println(startToMid1+mid1ToEnd);
			}
		}
		else if(startToMid1*mid1ToMid2*mid2ToEnd==0) {
			if(startToMid2*mid2ToMid1*mid1ToEnd==0) {
				System.out.println(-1);
			}
			else {
				System.out.println(startToMid2+mid2ToMid1+mid1ToEnd);
			}
		}
		else if(startToMid2*mid2ToMid1*mid1ToEnd==0) {
			System.out.println(startToMid1+mid1ToMid2+mid2ToEnd);
		}
		else if(startToMid1+mid1ToMid2+mid2ToEnd<startToMid2+mid2ToMid1+mid1ToEnd) {
			System.out.println(startToMid1+mid1ToMid2+mid2ToEnd);
		}
		else {
			System.out.println(startToMid2+mid2ToMid1+mid1ToEnd);
		}
	}

}

'Exercises > 길찾기' 카테고리의 다른 글

백준 1504  (0) 2019.01.30
1504 cpp  (0) 2018.05.05
백준 1504 수정  (0) 2018.05.05
백준 1504  (2) 2018.05.04
백준 문제 1504  (0) 2018.05.03

cpp로 짰으나 여전히 시간 초과.



#include<stdio.h>
#define MAX_COL 800;
void shortestRouteMtx(int route[][MAX_COL], int size){
	bool unchanged=true;
	int unchangedCheck=0;
	for(int i=0;i<size;i++){
		unchanged=true;
		for(int j=0;j<size;j++){
			for(int k=0;k<size;k++){
				unchangedCheck=route[j][k];
				if(j==k){
					route[j][k]=0;
				}
				else{
					for(int l=0;l<size;l++){
						if(route[j][l]!=0 && route[l][k]!=0){
							if(route[j][k]==0 || (route[j][k]>route[j][l]+route[l][k] && route[j][k]!=0)){
								route[j][k]=route[j][l]+route[l][k];
							}
						}
					}
				}
				if(unchanged){
					unchanged=(unchangedCheck==route[j][k]);
				}
			}
		}
		if(unchanged){
			break;
		}
	}
	return;
}
int main(){
	int n=0, k=0;
	scanf("%d",&n);
	scanf("%d",&k);
	int route[n][MAX_COL];
	for(int i=0;i<n;i++){
		for(int j=0;j<j++){
			route[i][j]=0;
		}
	}
	int start,end,distance;
	for(int i=0;i<k;i++){
		scanf("%d",&start);
		scanf("%d",&end);
		scanf("%d",&distance);
		route[start-1][end-1]=distance;
		route[end-1][start-1]=distance;
	}
	shortestRouteMtx(route,n);
	int mid1,mid2;
	scanf("%d",&mid1);
	scanf("%d",&mid2);
	
	int startToMid1=route[0][mid1-1];
	int mid1ToMid2=route[mid1-1][mid2-1];
	int mid2ToEnd=route[mid2-1][n-1];
	int startToMid2=route[0][mid2-1];
	int mid2ToMid1=route[mid2-1][mid1-1];
	int mid1ToEnd=route[mid1-1][n-1];
	
	if(startToMid1*mid1ToMid2*mid2ToEnd==0) {
		if(startToMid2*mid2ToMid1*mid1ToEnd==0) {
			printf("%d",-1);
		}
		else {
			printf("%d",startToMid2+mid2ToMid1+mid1ToEnd);
		}
	}
	else if(startToMid2*mid2ToMid1*mid1ToEnd==0) {
		printf("%d",startToMid1+mid1ToMid2+mid2ToEnd);
	}
	else if(startToMid1+mid1ToMid2+mid2ToEnd<startToMid2+mid2ToMid1+mid1ToEnd) {
		printf("%d",startToMid1+mid1ToMid2+mid2ToEnd);
	}
	else {
		printf("%d",startToMid2+mid2ToMid1+mid1ToEnd);
	}
	return 0;
}

'Exercises > 길찾기' 카테고리의 다른 글

백준 1504  (0) 2019.01.30
백준 1504  (1) 2018.05.06
백준 1504 수정  (0) 2018.05.05
백준 1504  (2) 2018.05.04
백준 문제 1504  (0) 2018.05.03

대부분 생각한 사항을 수정.

아래는 코드

import java.util.Scanner;

public class Main {	
	public void shortestRouteMtx(int[][] route){
		int n=route.length;
		boolean unchanged=true;
		int unchangedCheck=0;
		for(int i=0;i<n;i++) { // considering path with i intermediate points (considering staying for some steps)  
			unchanged=true; // default:unchanged;
			for(int j=0;j<n;j++) {
				for(int k=0;k<n;k++) {
					unchangedCheck=route[j][k]; // For checking, save the info before update
					if(j==k) {
						route[j][k]=0; // the distance from a point to itself is always 0
					}
					else {
						for(int l=0;l<n;l++) { // consider the path with intermediate point l;, sweep all possible l
							if(route[j][l]!=0 && route[l][j]!=0) { // if one of them is zero, the route is impossible or staying once. In both cases, don't need to change
								if(route[j][k]==0 || (route[j][k]>route[j][l]+route[l][k] && route[j][k]!=0))
										route[j][k]=route[j][l]+route[l][k];
							}
						}
					}
					if(unchanged) { // if at least one entry is changed, don't need to check the others
						unchanged=(unchangedCheck==route[j][k]);
					}
				}
			}
			if(unchanged) { // for whole process, nothing changed, break the loop;
				System.out.println("break 할 때의 i값은 "+i+"입니다.");
				break;
			}
		}
	}

	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		Main main=new Main();
		int N=sc.nextInt(), m=sc.nextInt();
		int[][] route=new int[N][N];
		for(int i=0;i<m;i++) {
			int from=sc.nextInt(), to=sc.nextInt(), distance=sc.nextInt(); // input route information 
			route[from-1][to-1]=distance;
			route[to-1][from-1]=distance;
		}
		int mid1=sc.nextInt(), mid2=sc.nextInt();
		long a=System.currentTimeMillis();
		main.shortestRouteMtx(route);

		int startToMid1=route[0][mid1-1];
		int mid1ToMid2=route[mid1-1][mid2-1];
		int mid2ToEnd=route[mid2-1][N-1];
		int startToMid2=route[0][mid2-1];
		int mid2ToMid1=route[mid2-1][mid1-1];
		int mid1ToEnd=route[mid1-1][N-1];
		if(startToMid1*mid1ToMid2*mid2ToEnd==0) {
			if(startToMid2*mid2ToMid1*mid1ToEnd==0) {
				System.out.println(-1);
			}
			else {
				System.out.println(startToMid2+mid2ToMid1+mid1ToEnd);
			}
		}
		else if(startToMid2*mid2ToMid1*mid1ToEnd==0) {
			System.out.println(startToMid1+mid1ToMid2+mid2ToEnd);
		}
		else if(startToMid1+mid1ToMid2+mid2ToEnd<startToMid2+mid2ToMid1+mid1ToEnd) {
			System.out.println(startToMid1+mid1ToMid2+mid2ToEnd);
		}
		else {
			System.out.println(startToMid2+mid2ToMid1+mid1ToEnd);
		}
		System.out.println((System.currentTimeMillis()-a)/1000.0);
	}
}

'Exercises > 길찾기' 카테고리의 다른 글

백준 1504  (0) 2019.01.30
백준 1504  (1) 2018.05.06
1504 cpp  (0) 2018.05.05
백준 1504  (2) 2018.05.04
백준 문제 1504  (0) 2018.05.03

아래는 수정한 코드. 런타임 에러가 없어진 것으로 메모리 제한에는 걸리지 않지만 시간초과가 됨.

일단 C로 고쳐서 짜 보고 C에서도 시간초과가 뜨면 조금 더 수정해서 필요없는 계산을 날려야 할 듯.

한 단계를 거칠 때 모든 루트를 다 고려하는 것이 아니라 한 번에 한 루트의 최단거리를 계산하는 방향으로 잡게 될 듯.

아래는 약간 수정한 코드.



import java.util.Scanner;

public class Main {	
	public int[][] shortestRouteMtx(int[][] input){
		int n=input.length;
		int[][] route0=new int[n][n];
		int[][] route1=new int[n][n];
		boolean parity=true;
		route0=input;
		for(int i=0;i<n;i++) {
			route1=new int[n][n];
			parity=true;
			for(int j=0;j<n;j++) {
				for(int k=0;k<n;k++) {
					if(j==k) {
						route1[j][k]=0;
					}
					else {
						for(int l=0;l<n;l++) {
							if(route1[j][k]==0) {
								if((j==l || l==k) || (route0[j][l]!=0 && route0[l][k]!=0)) {
									route1[j][k]=route0[j][l]+route0[l][k];
								}
							}
							else if((j==l || l==k) || (route0[j][l]!=0 && route0[l][k]!=0) && route1[j][k]>route0[j][l]+route0[l][k]){
								route1[j][k]=route0[j][l]+route0[l][k];
							}
						}
					}
					if(parity && route0[j][k]!=route1[j][k]) {
						parity=false;
					}
				}
			}
			if(parity) {
				break;
			}
		}
		return route0;
	}

	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		Main main=new Main();
		int N=sc.nextInt(), m=sc.nextInt();
		int[][] route=new int[N][N];
		for(int i=0;i<m;i++) {
			int a=sc.nextInt(), b=sc.nextInt(), c=sc.nextInt();
			route[a-1][b-1]=c;
			route[b-1][a-1]=c;
		}
		int mid1=sc.nextInt(), mid2=sc.nextInt();
		route=main.shortestRouteMtx(route);

		int startToMid1=route[0][mid1-1];
		int mid1ToMid2=route[mid1-1][mid2-1];
		int mid2ToEnd=route[mid2-1][N-1];
		int startToMid2=route[0][mid2-1];
		int mid2ToMid1=route[mid2-1][mid1-1];
		int mid1ToEnd=route[mid1-1][N-1];
		if(startToMid1*mid1ToMid2*mid2ToEnd==0) {
			if(startToMid2*mid2ToMid1*mid1ToEnd==0) {
				System.out.println(-1);
			}
			else {
				System.out.println(startToMid2+mid2ToMid1+mid1ToEnd);
			}
		}
		else if(startToMid2*mid2ToMid1*mid1ToEnd==0) {
			System.out.println(startToMid1+mid1ToMid2+mid2ToEnd);
		}
		else if(startToMid1+mid1ToMid2+mid2ToEnd<startToMid2+mid2ToMid1+mid1ToEnd) {
			System.out.println(startToMid1+mid1ToMid2+mid2ToEnd);
		}
		else {
			System.out.println(startToMid2+mid2ToMid1+mid1ToEnd);
		}
	}
}

'Exercises > 길찾기' 카테고리의 다른 글

백준 1504  (0) 2019.01.30
백준 1504  (1) 2018.05.06
1504 cpp  (0) 2018.05.05
백준 1504 수정  (0) 2018.05.05
백준 문제 1504  (0) 2018.05.03

방향성이 없는 그래프가 주어진다. 세준이는 1번 정점에서 N번 정점으로 최단 거리로 이동하려고 한다. 또한 세준이는 두 가지 조건을 만족하면서 이동하는 특정한 최단 경로를 구하고 싶은데, 그것은 바로 임의로 주어진 두 정점은 반드시 통과해야 한다는 것이다.

세준이는 한번 이동했던 정점은 물론, 한번 이동했던 간선도 다시 이동할 수 있다. 하지만 반드시 최단 경로로 이동해야 한다는 사실에 주의하라. 1번 정점에서 N번 정점으로 이동할 때, 주어진 두 정점을 반드시 거치면서 최단 경로로 이동하는 프로그램을 작성하시오.



import java.util.Scanner;

public class Main {	
	public int[][][] matrixExp(int[][] input){
		int n=input.length;
		int[][][] route=new int[n][n][n];
		
		route[0]=input;
		for(int i=1;i<n;i++) {
			for(int j=0;j<n;j++) {
				for(int k=0;k<n;k++) {
					if(j==k) {
						route[i][j][k]=0;
					}
					else {
						for(int l=0;l<n;l++) {
							if(route[i][j][k]==0) {
								if(j==l || l==k) {
									route[i][j][k]=route[i-1][j][l]+route[0][l][k];
								}
								else if(route[i-1][j][l]!=0 && route[0][l][k]!=0) {
									route[i][j][k]=route[i-1][j][l]+route[0][l][k];
								}
							}
							else if(route[i-1][j][l]!=0 && route[0][l][k]!=0 && route[i][j][k]>route[i-1][j][l]+route[0][l][k]){
								route[i][j][k]=route[i-1][j][l]+route[0][l][k];
							}
						}
					}
				}
			}
		}
		return route;
	}
	
	public int chooseMin(int[][][] matrixExp, int start, int end) {
		int n=matrixExp.length;
		int min=0;
		
		for(int i=0;i<n;i++) {
			if(min==0) {
				min=matrixExp[i][start-1][end-1];
			}
			else if(matrixExp[i][start-1][end-1]!=0 && min>matrixExp[i][start-1][end-1]) {
				min=matrixExp[i][start-1][end-1];
			}
		}
		return min;
	}

	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		Main main=new Main();
		int N=sc.nextInt(), m=sc.nextInt();
		int[][][] route=new int[N][N][N];
		for(int i=0;i<m;i++) {
			int a=sc.nextInt(), b=sc.nextInt(), c=sc.nextInt();
			route[0][a-1][b-1]=c;
			route[0][b-1][a-1]=c;
		}
		int mid1=sc.nextInt(), mid2=sc.nextInt();
		route=main.matrixExp(route[0]);

		int startToMid1=main.chooseMin(route, 1, mid1);
		int mid1ToMid2=main.chooseMin(route, mid1, mid2);
		int mid2ToEnd=main.chooseMin(route, mid2, N);
		int startToMid2=main.chooseMin(route, 1, mid2);
		int mid2ToMid1=main.chooseMin(route, mid2, mid1);
		int mid1ToEnd=main.chooseMin(route, mid1, N);
		if(startToMid1*mid1ToMid2*mid2ToEnd==0) {
			if(startToMid2*mid2ToMid1*mid1ToEnd==0) {
				System.out.println(-1);
			}
			else {
				System.out.println(startToMid2+mid2ToMid1+mid1ToEnd);
			}
		}
		else if(startToMid2*mid2ToMid1*mid1ToEnd==0) {
			System.out.println(startToMid1+mid1ToMid2+mid2ToEnd);
		}
		else if(startToMid1+mid1ToMid2+mid2ToEnd<startToMid2+mid2ToMid1+mid1ToEnd) {
			System.out.println(startToMid1+mid1ToMid2+mid2ToEnd);
		}
		else {
			System.out.println(startToMid2+mid2ToMid1+mid1ToEnd);
		}
	}
}

오류가 난 코드. 메모리 오버도 런타임 에러로 나온다는 당연한 사실을 생각하지 못하고, 런타임 에러가 나는 것을 인덱스 오류라고만 생각했다. 당연히 3dimensional array를 쓰면서 range를 800까지 사용하면 메모리 오버가 날 수 밖에 없을 듯. 일부만 사용하는 것이 아니라 전체를 넘겨주도록 했기 때문에.

중간점이 있기 때문에 끝까지 track할 필요는 없을 것. 그리고 어느 시점에서 더 생각할 필요가 없는지 체크해야 할 듯.

'Exercises > 길찾기' 카테고리의 다른 글

백준 1504  (0) 2019.01.30
백준 1504  (1) 2018.05.06
1504 cpp  (0) 2018.05.05
백준 1504 수정  (0) 2018.05.05
백준 1504  (2) 2018.05.04

+ Recent posts