11779번: 최소비용 구하기 2

첫째 줄에 도시의 개수 n(1≤n≤1,000)이 주어지고 둘째 줄에는 버스의 개수 m(1≤m≤100,000)이 주어진다. 그리고 셋째 줄부터 m+2줄까지 다음과 같은 버스의 정보가 주어진다. 먼저 처음에는 그 버스

www.acmicpc.net

 

 

 

 


 

 

 

  • 풀이

 

주어진 연결된 노드 중 start에서 end까지 가는 최소비용을 구하면 되는 알고리즘 입니다.

 

우선순위큐를 사용하지 않은 다익스트라 알고리즘을 사용하는 경우 O(V^2)시간이 걸리기 때문에 100000*100000으로 1초가 넘어가게 되어 시간초과가 나게됩니다. 이 문제의 핵심은 우선순위큐를 사용한 다익스트라 알고리즘을 사용하여 O(ElogV)의 시간으로 풀어내야 하는 문제입니다. 

 

현재까지 누적된 distance값으로 우선순위큐를 매겨줍니다. 이렇게되면 가장 빨리 end에 도착한 값이 최소 비용으로 도착한 값이기 때문에 반복문을 종료하여도 됩니다. 

 

추가적으로 추적은 부모노드를 설정함으로써 역추적하여 구해주었습니다.

 

  • 코드

 

 

import java.io.IOException;
import java.io.InputStream;
import java.util.*;

public class Main {
	static StringBuilder sb;
	static int N;
	static int[] parent, distance;
	static ArrayList<Node>[] array;

	public static void main(String[] args) throws Exception {
		SetData();
		System.out.println(sb);
	}

	// 데이터
	private static void SetData() throws Exception {
		InputReader in = new InputReader(System.in);

		sb = new StringBuilder();
		N = in.nextInt();
		array = new ArrayList[N+1];
		for(int i = 1; i <= N; i++)
			array[i] = new ArrayList<>();
		
		int count = in.nextInt();
		
		for(int i = 0; i < count ; i++) {
			int a = in.nextInt();
			int b = in.nextInt();
			int c = in.nextInt();
			array[a].add(new Node(b,c));
		}
		
		int start = in.nextInt();
		int end = in.nextInt();
		
		dijkstra(start, end);
		sb.append(distance[end]).append("\n");
		
		Stack<Integer> stack = new Stack<>();
        while(end != 0) {
        	stack.add(end);
            end = parent[end];
        }
		sb.append(stack.size()).append("\n");
		
		while(!stack.isEmpty())
			sb.append(stack.pop() + " ");
	}

	private static void dijkstra(int start, int end) {
		PriorityQueue<Node> pq = new PriorityQueue<>();
        pq.offer(new Node(start, 0));
		
        parent = new int[N+1];
        distance = new int[N+1];
        Arrays.fill(distance, 100000000);
        distance[start] = 0;
        
        while(!pq.isEmpty()){
            Node now = pq.poll();
            if(now.x == end) break;

            for(Node node : array[now.x]) {
            	if(distance[node.x] > distance[now.x] + node.distance){
            		distance[node.x] = distance[now.x] + node.distance;
                    pq.add(new Node(node.x, distance[node.x]));
                    parent[node.x] = now.x;
                }
            }
        }
	}
}

class Node implements Comparable<Node>{
	int x;
	int distance;
	
	public Node(int x, int distance) {
		this.x = x;
		this.distance = distance;
	}

	@Override
	public int compareTo(Node o) {
		// TODO Auto-generated method stub
		return this.distance - o.distance;
	}
}

class InputReader {
	private final InputStream stream;
	private final byte[] buf = new byte[8192];
	private int curChar, snumChars;

	public InputReader(InputStream st) {
		this.stream = st;
	}

	public int read() {
		if (snumChars == -1)
			throw new InputMismatchException();
		if (curChar >= snumChars) {
			curChar = 0;
			try {
				snumChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (snumChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int nextInt() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public long nextLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public int[] nextIntArray(int n) {
		int a[] = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		return a;
	}

	public String nextLine() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isEndOfLine(c));
		return res.toString();
	}

	public boolean isSpaceChar(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	private boolean isEndOfLine(int c) {
		return c == '\n' || c == '\r' || c == -1;
	}
}

 

4485번: 녹색 옷 입은 애가 젤다지?

젤다의 전설 게임에서 화폐의 단위는 루피(rupee)다. 그런데 간혹 '도둑루피'라 불리는 검정색 루피도 존재하는데, 이걸 획득하면 오히려 소지한 루피가 감소하게 된다! 젤다의 전설 시리즈의 주

www.acmicpc.net

 

 

 


 

 

 

  • 풀이

 

(0,0) 부터 (N-1,N-1)까지 상,하,좌,우로 1칸씩 이동하면서 가장 적은 도둑루피의 수를 만나면서 가는 합 중 가장 적은 합을 출력하면 되는 문제입니다.

 

문제를 읽으면서 가장 먼저 생각난 알고리즘은 가장 적은 수로만 (N-1, N-1)로 가기 위한 다익스트라였고, 다익스트라를 사용하여 알고리즘을 풀어냈습니다.

 

풀이 과정은 다음과 같습니다.

배열의 탐색은 가는 길을 가장 적은 수로만 가기 위해 distance 배열을 통해 현재 지나온 값보다 적은 값만 지나갈 수 있도록 하였습니다. 처음 초기화는 N의 가장 큰 값인 125와 도둑루피의 수중 최대값인 9를 곱한 125*125*9인 140625보다 큰 150000으로 초기화 하였습니다.

 

그래프 탐색이 종료되면 (N-1,N-1)에는 가장 적은 루피의 수를 만나고온 합이 저장되어있습니다.

 

 

  • 코드

 

import java.io.IOException;
import java.io.InputStream;
import java.util.*;

public class Main {
	static StringBuilder sb;
	static int N;
	static int[][] array;
	static int[] dx = {0,0,-1,1};
	static int[] dy = {-1,1,0,0};

	public static void main(String[] args) throws Exception {
		SetData();
		System.out.println(sb);
	}

	// 데이터
	private static void SetData() throws Exception {
		InputReader in = new InputReader(System.in);

		sb = new StringBuilder();
		int index = 1;
		while(true) {
			N = in.nextInt();
			if(N == 0) break;
			
			array = new int[N][N];
			for(int i = 0; i < N; i++) {
				for(int j = 0; j < N; j++) {
					array[i][j] = in.nextInt();
				}
			}
			
			sb.append("Problem "+(index++)+ ": "+ dijkstra()).append("\n");
		}
	}

	private static int dijkstra() {
		Queue<Node> queue = new LinkedList<>();
        queue.offer(new Node(0, 0));
		
        int[][] distance = new int[N][N];
        
        for(int i = 0; i < N; i++)
        	Arrays.fill(distance[i], 150000);
       
        distance[0][0] = array[0][0];
        
        while (!queue.isEmpty()) {
            Node nowNode = queue.poll();
 
            for(int direction = 0; direction < 4; direction++) {
            	int r = nowNode.x + dx[direction];
            	int c = nowNode.y + dy[direction];
            	
            	if(r < 0 || c < 0 || r >= N || c >= N) continue;
            	if(distance[r][c] <= distance[nowNode.x][nowNode.y] + array[r][c]) continue;
            	
            	distance[r][c] = distance[nowNode.x][nowNode.y] + array[r][c];
            	queue.add(new Node(r, c));
            }
        }
		return distance[N-1][N-1];
		
	}
}

class Node {
	int x;
	int y;
	
	public Node(int x, int y) {
		this.x = x;
		this.y = y;
	}
}

class InputReader {
	private final InputStream stream;
	private final byte[] buf = new byte[8192];
	private int curChar, snumChars;

	public InputReader(InputStream st) {
		this.stream = st;
	}

	public int read() {
		if (snumChars == -1)
			throw new InputMismatchException();
		if (curChar >= snumChars) {
			curChar = 0;
			try {
				snumChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (snumChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int nextInt() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public long nextLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public int[] nextIntArray(int n) {
		int a[] = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		return a;
	}

	public String nextLine() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isEndOfLine(c));
		return res.toString();
	}

	public boolean isSpaceChar(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	private boolean isEndOfLine(int c) {
		return c == '\n' || c == '\r' || c == -1;
	}
}

 

1238번: 파티

첫째 줄에 N(1 ≤ N ≤ 1,000), M(1 ≤ M ≤ 10,000), X가 공백으로 구분되어 입력된다. 두 번째 줄부터 M+1번째 줄까지 i번째 도로의 시작점, 끝점, 그리고 이 도로를 지나는데 필요한 소요시간 Ti가 들어

www.acmicpc.net

 

 

 

 


 

 

  • 풀이

 

X번 마을을 제외한 모든 마을에 있는 사람이 X번 마을에 방문한 뒤 돌아가는 마을 중 최대값을 출력하면 되는 문제입니다. (단, 모든 마을의 사람은 최단거리로 움직입니다.)

 

처음 문제를 읽고 플로이드와샬을 통해 풀어보려고 했지만 N의 최대값이 1,000이고 시간제한이 1초인 것을 보고 O(N^3)인 플로이드와샬로는 풀지 못한다고 생각하였습니다. 

 

저는 한점을 통해 모든 점으로 가는 최단거리를 찾는 다익스트라 방법을 사용했고 우선순위큐를 사용하는 다익스트라 알고리즘은 O(VlogV)이므로 시간은 충분했습니다. 문제에서 주어지는 입력은 단방향이므로 X마을로 오고, 가는 방법을 구하기위해 a->b로 오는 자료구조 한개, b->a로가는 자료구조 한개를 추가로 사용해서 두번의 다익스트라를 통해 최단거리를 구해주었습니다.

 

 

 

  • 코드

 

import java.io.IOException;
import java.io.InputStream;
import java.util.*;

public class Main {
	static int N,M,X,answer;

	public static void main(String[] args) throws Exception {
		SetData();
		System.out.println(answer);
	}

	// 데이터
	private static void SetData() throws Exception {
		InputReader in = new InputReader(System.in);

		answer = 0;
		N = in.nextInt();
		M = in.nextInt();
		X = in.nextInt();
		ArrayList<Node>[] array = new ArrayList[N+1];
		ArrayList<Node>[] reArray = new ArrayList[N+1];
		for(int i = 1; i <= N; i++)  {
			array[i] = new ArrayList<>();
			reArray[i] = new ArrayList<>();
		}
		
		for(int i = 0 ; i < M; i++) {
			int a = in.nextInt();
			int b = in.nextInt();
			int w = in.nextInt();
			array[a].add(new Node(b, w));
			reArray[b].add(new Node(a, w));
		}
		
		int[] distance = dijkstra(array);
		int[] nDistance = dijkstra(reArray);
		
		for(int i = 1; i <= N; i++) {
			answer = Math.max(answer, distance[i] + nDistance[i]);
		}
	}

	private static int[] dijkstra(ArrayList<Node>[] array) {
		PriorityQueue<Node> pq = new PriorityQueue<>();
        pq.offer(new Node(X, 0));
		
        boolean[] check = new boolean[N + 1];
        int[] distance = new int[N + 1];
        Arrays.fill(distance, 10000000);
       
        distance[X] = 0;
        
        while (!pq.isEmpty()) {
            Node nowNode = pq.poll();
 
            if (check[nowNode.x])  continue;
            
            check[nowNode.x] = true;
            for(int i = 0; i < array[nowNode.x].size(); i++) {
            	Node node = array[nowNode.x].get(i);
            	if (check[node.x] || distance[node.x] <= distance[nowNode.x] + node.distance) continue;
            	
            	distance[node.x] = distance[nowNode.x] + node.distance;
                pq.add(new Node(node.x, distance[node.x]));
            }
        }
		return distance;
		
	}
}

class Node implements Comparable<Node> {
	int x;
	int distance;
	
	public Node(int x, int distance) {
		this.x = x;
		this.distance = distance;
	}

	@Override
	public int compareTo(Node node) {
		// TODO Auto-generated method stub
		return this.distance - node.distance;
	}
}

class InputReader {
	private final InputStream stream;
	private final byte[] buf = new byte[8192];
	private int curChar, snumChars;

	public InputReader(InputStream st) {
		this.stream = st;
	}

	public int read() {
		if (snumChars == -1)
			throw new InputMismatchException();
		if (curChar >= snumChars) {
			curChar = 0;
			try {
				snumChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (snumChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int nextInt() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public long nextLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public int[] nextIntArray(int n) {
		int a[] = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		return a;
	}

	public String nextLine() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isEndOfLine(c));
		return res.toString();
	}

	public boolean isSpaceChar(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	private boolean isEndOfLine(int c) {
		return c == '\n' || c == '\r' || c == -1;
	}
}

 

5427번: 불

상근이는 빈 공간과 벽으로 이루어진 건물에 갇혀있다. 건물의 일부에는 불이 났고, 상근이는 출구를 향해 뛰고 있다. 매 초마다, 불은 동서남북 방향으로 인접한 빈 공간으로 퍼져나간다. 벽에

www.acmicpc.net

 

 

 

 


 

 

 

 

  • 풀이

 

문제는 어렵기보단 입력값이 크지 않기때문에 문제에 조건대로 구현만 잘하면되는 문제입니다.

 

문제의 조건은 다음과 같습니다.

  • '.': 빈 공간
  • '#': 벽
  • '@': 상근이의 시작 위치
  • '*': 불

의 입력에서 @인 상근이를 벽과 불을 피해서 배열 밖으로 빼낼 수 있으면 최소값 출력, 빼낼 수 없다면 IMPOSSIZBLE을 출력하면 되는 문제입니다. 단, *인 불과 @인 상근이는 1초마다 상,하,좌,우로 1칸씩 움직일 수 있습니다. 또한 불이 불이 먼저 번지기 때문에 상근이는 현재 불이 상, 하, 좌, 우로 퍼진 위치로 갈 수 없고 불은 현재 상근이가 위치한 좌표로 번질 수 있지만 상근이는 움직일 수 있다면 상관없습니다. 여기까지가 문제에 대한 조건들 입니다.

 

 

풀이 방법은 bfs를 사용했고, queue에 현재 저장되어있는 불들을 다 번지게 한 뒤, 상근이를 움직일 수 있게 해주었습니다. 만약, 상근이가 범위 밖으로 갈 수 있을 시 움직인 횟수를 return해주었고 상근이가 더이상 움직일 수 없어서 반복문이 종료되게 될때까지 return하지 못했다면 상근이는 건물을 벗어날 수 없는 것이기 때문에 -1을 return 해주었습니다.

 

 

  • 코드

 

import java.io.IOException;
import java.io.InputStream;
import java.util.*;

public class Main {
	static int w, h;
	static StringBuilder sb;
	static char[][] array;
	static boolean[][] check;
	static Queue<Sang> sang;
	static Queue<Node> fire;
	static int[] dx = { 0, 0, -1, 1 };
	static int[] dy = { -1, 1, 0, 0 };

	public static void main(String[] args) throws Exception {
		SetData();
		System.out.println(sb);
	}

	// 데이터
	private static void SetData() throws Exception {
		InputReader in = new InputReader(System.in);

		sb = new StringBuilder();
		int testcase = in.nextInt();
		for (int i = 0; i < testcase; i++) {
			w = in.nextInt();
			h = in.nextInt();
			array = new char[h][w];
			check = new boolean[h][w];
			sang = new LinkedList<>();
			fire = new LinkedList<>();

			for (int a = 0; a < h; a++) {
				String s = in.nextLine();
				for (int b = 0; b < w; b++) {
					array[a][b] = s.charAt(b);
					if (array[a][b] == '*')
						fire.add(new Node(a, b));
					if (array[a][b] == '@')
						sang.add(new Sang(a, b, 0));
				}
			}

			int answer = bfs();
			if (answer == -1) {
				sb.append("IMPOSSIBLE").append("\n");
			} else {
				sb.append(answer).append("\n");
			}
		}

	}

	private static int bfs() {
		while (!sang.isEmpty()) {
			// 불 1초 이동 
			int fireSize = fire.size();
			for (int i = 0; i < fireSize; i++) {
				Node node = fire.poll();

				for (int direction = 0; direction < 4; direction++) {
					int r = node.x + dx[direction];
					int c = node.y + dy[direction];

					if (r < 0 || c < 0 || r >= h || c >= w)
						continue;
					if (array[r][c] == '#' || array[r][c] == '*')
						continue;

					array[r][c] = '*';
					fire.add(new Node(r, c));
				}
			}

			
			// 상근이 1초 이동 
			int sangSize = sang.size();

			for (int i = 0; i < sangSize; i++) {
				Sang temp = sang.poll();
				check[temp.x][temp.y] = true;

				for (int direction = 0; direction < 4; direction++) {
					int r = temp.x + dx[direction];
					int c = temp.y + dy[direction];

					if (r < 0 || c < 0 || r >= h || c >= w)
						return temp.count + 1;
					if (array[r][c] != '.' || check[r][c])
						continue;

					check[r][c] = true;
					sang.add(new Sang(r, c, temp.count + 1));
				}
			}
		}

		return -1;
	}

}

class Node {
	int x;
	int y;

	public Node(int x, int y) {
		this.x = x;
		this.y = y;
	}
}

class Sang {
	int x;
	int y;
	int count;

	public Sang(int x, int y, int count) {
		this.x = x;
		this.y = y;
		this.count = count;
	}
}

class InputReader {
	private final InputStream stream;
	private final byte[] buf = new byte[8192];
	private int curChar, snumChars;

	public InputReader(InputStream st) {
		this.stream = st;
	}

	public int read() {
		if (snumChars == -1)
			throw new InputMismatchException();
		if (curChar >= snumChars) {
			curChar = 0;
			try {
				snumChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (snumChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int nextInt() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public long nextLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public int[] nextIntArray(int n) {
		int a[] = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		return a;
	}

	public String nextLine() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isEndOfLine(c));
		return res.toString();
	}

	public boolean isSpaceChar(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	private boolean isEndOfLine(int c) {
		return c == '\n' || c == '\r' || c == -1;
	}
}

 

 

코딩테스트 연습 - 12주차

XX게임에는 피로도 시스템(0 이상의 정수로 표현합니다)이 있으며, 일정 피로도를 사용해서 던전을 탐험할 수 있습니다. 이때, 각 던전마다 탐험을 시작하기 위해 필요한 "최소 필요 피로도"와 던

programmers.co.kr

 

 


 

 

  • 풀이

 

처음엔 정렬한 후 풀어보려고했지만 입력값이 까다로워서 정확한 답을 구현할 수 없었습니다.

 

던전의 수가 최대 8개로 많지 않기때문에 완탐을 했습니다.

dfs 방식으로 완전 탐색 했습니다.

 

 

  • 코드

 

import java.util.*;

class Solution {
    static boolean[] check;
    static int answer;
    
    public int solution(int k, int[][] dungeons) {
        check = new boolean[dungeons.length];
        answer = 0;
        
        for(int i = 0; i < dungeons.length; i++){
            if(dungeons[i][0] > k) continue;
            
            check[i] = true;
            dfs(k-dungeons[i][1], dungeons, 1);
            check[i] = false;
        }
        
        return answer;
    }
    
    private static void dfs(int k, int[][] dungeons, int count){
        answer = Math.max(answer, count);
        
       for(int i = 0; i < dungeons.length; i++){
            if(dungeons[i][0] > k || check[i]) continue;
            
            check[i] = true;
            dfs(k-dungeons[i][1], dungeons, count+1);
            check[i] = false;
        }
    }
}

 

 

1167번: 트리의 지름

트리가 입력으로 주어진다. 먼저 첫 번째 줄에서는 트리의 정점의 개수 V가 주어지고 (2 ≤ V ≤ 100,000)둘째 줄부터 V개의 줄에 걸쳐 간선의 정보가 다음과 같이 주어진다. 정점 번호는 1부터 V까지

www.acmicpc.net

 

 

 

 


 

 

 

  • 풀이

 

트리의 자료구조 중 임의의 두점의 거리가 가장 먼 거리를 출력해주면되는 문제입니다.

 

먼저, 트리의 연결은 ArrayList 배열을 통해 연결해 주었습니다.

 

그 후, 트리 탐색은 dfs방식을 사용했습니다.

 

첫번째 풀이는 모든 노드들에서 시작해서 모든 노드들을 돌면서 가장 거리의 합이 높은 노드 길이의 합을 게속 초기화 시켜주는 방식을 사용했습니다. 하지만 해당 코드는 시간 초과가 떴습니다. 해당 문제의 제한 시간은 2초이고 최대 노드의 수는 100,000이기때문이였습니다.

 

바꿀 방법을 생각해보니 모든 노드의 시작부터 할 필요가 없었습니다. 실제로 단 두 번의 시작노드를 통해 정답을 뽑아낼 수 있습니다. 단 두번으로 할 수 있는 근거는 트리입니다. 모든 노드들은 연결되어 있습니다. 한 노드에서 시작해서 가장 먼 노드를 초기화시켜준 뒤 가장 먼 노드부터 시작해서 가장 먼 노드를 구해주면 값을 뽑아낼 수 있습니다. 

 

모두 이어져있기 때문에 한 노드에서 가장 먼 노드를 구하면 가장 먼노드부터 그전에 시작한 노드까지의 합과 그전에 시작한 노드부터 두번째로 먼 노드의 합까지 더할 수 있기 때문입니다.

 

 

  • 시간초과 코드

 

import java.io.IOException;
import java.io.InputStream;
import java.util.*;

public class Main {
	static ArrayList[] node;
	static int answer;
	static boolean[] check;
	
	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		SetData();
		System.out.println(answer);
	}

	private static void SetData() throws Exception {
		InputReader in = new InputReader(System.in);

		int V = in.nextInt();
		node = new ArrayList[V+1];
		check = new boolean[V+1];
		answer = 0;
		
		for(int i = 1; i <= V ;i++)
			node[i] = new ArrayList<Node>();
		
		for(int i = 0; i < V; i++) {
			int now = in.nextInt();
			
			while(true) {
				int nodeNumber = in.nextInt();
				if(nodeNumber == -1) break;
				int distance = in.nextInt();
				
				node[now].add(new Node(nodeNumber, distance));
			}
		}
		
		for(int i = 1; i <= V; i++) {
			check[i] = true;
			bfs(i, 0);
			check[i] = false;
		}
	}
	
	private static void bfs(int now, int sum) {
		if(answer < sum) {
			answer = sum;
		}
		
		for(int i = 0; i < node[now].size(); i++) {
			Node temp = (Node) node[now].get(i);
			
			if(check[temp.x]) continue;
			
			check[temp.x] = true;
			bfs(temp.x, sum + temp.distance);
			check[temp.x] = false;
		}
	}
}

class Node {
	int x;
	int distance;
	
	public Node(int x, int distance) {
		this.x = x;
		this.distance = distance;
	}
}

class InputReader {
	private final InputStream stream;
	private final byte[] buf = new byte[8192];
	private int curChar, snumChars;

	public InputReader(InputStream st) {
		this.stream = st;
	}

	public int read() {
		if (snumChars == -1)
			throw new InputMismatchException();
		if (curChar >= snumChars) {
			curChar = 0;
			try {
				snumChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (snumChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int nextInt() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public long nextLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public int[] nextIntArray(int n) {
		int a[] = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		return a;
	}

	public String nextLine() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isEndOfLine(c));
		return res.toString();
	}

	public boolean isSpaceChar(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	private boolean isEndOfLine(int c) {
		return c == '\n' || c == '\r' || c == -1;
	}
}

 

 

  • 통과 코드

 

import java.io.IOException;
import java.io.InputStream;
import java.util.*;

public class Main {
	static ArrayList[] node;
	static int answer, max;
	static boolean[] check;
	
	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		SetData();
		System.out.println(answer);
	}

	private static void SetData() throws Exception {
		InputReader in = new InputReader(System.in);

		int V = in.nextInt();
		node = new ArrayList[V+1];
		check = new boolean[V+1];
		answer = 0;
		max = 0;
		
		for(int i = 1; i <= V ;i++)
			node[i] = new ArrayList<Node>();
		
		for(int i = 0; i < V; i++) {
			int now = in.nextInt();
			
			while(true) {
				int nodeNumber = in.nextInt();
				if(nodeNumber == -1) break;
				int distance = in.nextInt();
				
				node[now].add(new Node(nodeNumber, distance));
			}
		}
		
		check[1] = true;
		bfs(1, 0);
		check[1] = false;
		
		check[max] = true;
		bfs(max, 0);
	}
	
	private static void dfs(int now, int sum) {
		if(answer < sum) {
			answer = sum;
			max = now;
		}
		
		for(int i = 0; i < node[now].size(); i++) {
			Node temp = (Node) node[now].get(i);
			
			if(check[temp.x]) continue;
			
			check[temp.x] = true;
			bfs(temp.x, sum + temp.distance);
			check[temp.x] = false;
		}
	}
}

class Node {
	int x;
	int distance;
	
	public Node(int x, int distance) {
		this.x = x;
		this.distance = distance;
	}
}

class InputReader {
	private final InputStream stream;
	private final byte[] buf = new byte[8192];
	private int curChar, snumChars;

	public InputReader(InputStream st) {
		this.stream = st;
	}

	public int read() {
		if (snumChars == -1)
			throw new InputMismatchException();
		if (curChar >= snumChars) {
			curChar = 0;
			try {
				snumChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (snumChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int nextInt() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public long nextLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public int[] nextIntArray(int n) {
		int a[] = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		return a;
	}

	public String nextLine() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isEndOfLine(c));
		return res.toString();
	}

	public boolean isSpaceChar(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	private boolean isEndOfLine(int c) {
		return c == '\n' || c == '\r' || c == -1;
	}
}

 

1939번: 중량제한

첫째 줄에 N, M(1 ≤ M ≤ 100,000)이 주어진다. 다음 M개의 줄에는 다리에 대한 정보를 나타내는 세 정수 A, B(1 ≤ A, B ≤ N), C(1 ≤ C ≤ 1,000,000,000)가 주어진다. 이는 A번 섬과 B번 섬 사이에 중량제한이

www.acmicpc.net

 

 


 

 

  • 풀이

 

처음에 백트래킹으로 풀려고 했지만 시간초과가 떴습니다.

M값은 10만이 최대이다. 시간초과가 왜??나는지에 대해서 아직 정확하게 모르겠습니다..

전체적으로 보았을 때 a에서 b로 가는 노드 중 가장 경로 중 가장 작은 값이 가장 큰 경로를 찾으면 되는 문제라 a에서 b로가는 모든 경로를 한번씩만 훑으면 더 빠른것이 아닌가??라는 생각이 들었습니다... (물론, a와 b가 가장 작은 값으로 한번에 연결되어있다면 굳이 모든 노드를 다 돌을 필요가 없지만 이러한 경우의 수 빼고는 다 돌아야되는 것이 맞는 것 아닌가...??!)

 

일단, 해결 풀이 방법은 이분탐색과 bfs를 사용했습니다. (알고리즘 분류를 통해 해결 방법을 찾았습니다.)

이분탐색의 기준은 weight으로 입력 중 최대 중량을 초기화시켜준 뒤 left = 0, right = 최대중량으로 이분탐색을 하며 bfs를 돌았습니다. mid값 보다 bfs를 돌며 큰 값이 있는 경우는 ritght를 mid -1로 초기화 시켜주고 문제가 없을 시 left를 mid + 1로 초기화시켜주었습니다.

 

 

 

  • 시간초과 코드 (백트래킹) 

 

import java.io.IOException;
import java.io.InputStream;
import java.util.*;

public class Main {
	static int N, M, answer;
	static ArrayList[] arrayList;
	static boolean[] check;

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		SetData();
		System.out.println(answer);
	}

	private static void SetData() throws Exception {
		InputReader in = new InputReader(System.in);

		N = in.nextInt();
		M = in.nextInt();
		answer = 0;
		arrayList = new ArrayList[N+1];
		check = new boolean[N+1];
		
		for(int i = 1; i <= N; i++)
			arrayList[i] = new ArrayList<Node>();
		
		for(int i = 0; i < M; i++) {
			int a = in.nextInt();
			int b = in.nextInt();
			int weight = in.nextInt();
			
			arrayList[a].add(new Node(b, weight));
			arrayList[b].add(new Node(a, weight));
		}
		
		int x = in.nextInt();
		int y = in.nextInt();
		check[x] = true;
		for(int i = 0; i < arrayList[x].size(); i++) {
			Node node = (Node) arrayList[x].get(i);
			
			check[node.a] = true;
			answer = Math.max(answer, dfs(node.weight, node.a, y));
			check[node.a] = false;
		}
	}
	
	private static int dfs(int min, int index, int b) {
		if(index == b) {
			return min;
		}
		
		for(int i = 0; i < arrayList[index].size(); i++) {
			Node node = (Node) arrayList[index].get(i);
			if(check[node.a]) continue;
			check[node.a] = true;
			min = Math.min(dfs(Math.min(min, node.weight), node.a, b),min);
			check[node.a] = false;
		}
		
		return min;
	}
}

class Node {
	int a;
	int weight;
	
	public Node(int a, int weight) {
		this.a = a;
		this.weight = weight;
	}
}

class InputReader {
	private final InputStream stream;
	private final byte[] buf = new byte[8192];
	private int curChar, snumChars;

	public InputReader(InputStream st) {
		this.stream = st;
	}

	public int read() {
		if (snumChars == -1)
			throw new InputMismatchException();
		if (curChar >= snumChars) {
			curChar = 0;
			try {
				snumChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (snumChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int nextInt() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public long nextLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public int[] nextIntArray(int n) {
		int a[] = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		return a;
	}

	public String nextLine() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isEndOfLine(c));
		return res.toString();
	}

	public boolean isSpaceChar(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	private boolean isEndOfLine(int c) {
		return c == '\n' || c == '\r' || c == -1;
	}
}

 

 

  • 통과 코드 (이분 탐색)

 

import java.io.IOException;
import java.io.InputStream;
import java.util.*;

public class Main {
	static int N, M, answer;
	static ArrayList[] arrayList;
	static boolean[] check;

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		SetData();
		System.out.println(answer);
	}

	private static void SetData() throws Exception {
		InputReader in = new InputReader(System.in);

		N = in.nextInt();
		M = in.nextInt();
		answer = 0;
		arrayList = new ArrayList[N+1];
		int max = 0;
		
		for(int i = 1; i <= N; i++)
			arrayList[i] = new ArrayList<Node>();
		
		for(int i = 0; i < M; i++) {
			int a = in.nextInt();
			int b = in.nextInt();
			int weight = in.nextInt();
			
			arrayList[a].add(new Node(b, weight));
			arrayList[b].add(new Node(a, weight));
			max = Math.max(weight, max);
		}
		
		int x = in.nextInt();
		int y = in.nextInt();
		
		int left = 0;
		int right = max;
		while(left<= right) {
			int mid = (left + right) / 2;
			
			check = new boolean[N+1];
			
			if(bfs(x,y,mid)) {
				left = mid + 1;
			} else {
				right = mid - 1;
			}
		}
		
		answer = right;
	}
	
	private static boolean bfs(int start, int end, int weigth) {
		Queue<Integer> queue = new LinkedList<>();
		queue.add(start);
		check[start] = true;
		
		while(!queue.isEmpty()) {
			int d = queue.poll();
			
			if(d == end) {
				return true;
			}
			
			for(int i = 0 ; i < arrayList[d].size(); i++) {
				Node node = (Node) arrayList[d].get(i);
                if (!check[node.a] && weigth <= node.weight) {
                    check[node.a] = true;
                    queue.add(node.a);
                }
            }
		}
		
		return false;
	}
}

class Node {
	int a;
	int weight;
	
	public Node(int a, int weight) {
		this.a = a;
		this.weight = weight;
	}
}

class InputReader {
	private final InputStream stream;
	private final byte[] buf = new byte[8192];
	private int curChar, snumChars;

	public InputReader(InputStream st) {
		this.stream = st;
	}

	public int read() {
		if (snumChars == -1)
			throw new InputMismatchException();
		if (curChar >= snumChars) {
			curChar = 0;
			try {
				snumChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (snumChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int nextInt() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public long nextLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public int[] nextIntArray(int n) {
		int a[] = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		return a;
	}

	public String nextLine() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isEndOfLine(c));
		return res.toString();
	}

	public boolean isSpaceChar(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	private boolean isEndOfLine(int c) {
		return c == '\n' || c == '\r' || c == -1;
	}
}

 

6064번: 카잉 달력

입력 데이터는 표준 입력을 사용한다. 입력은 T개의 테스트 데이터로 구성된다. 입력의 첫 번째 줄에는 입력 데이터의 수를 나타내는 정수 T가 주어진다. 각 테스트 데이터는 한 줄로 구성된다.

www.acmicpc.net

 

 

 

 


 

 

 

  • 풀이

 

처음에 문제풀 때 M*N의 시간복잡도로 풀어 시간초과가 났습니다.

 

해결방법은 유클리드 호제법을 통해 계산해야되는 경우의 수를 최대한 줄여줍니다.

 

해당 방법과 반복문을 최대한으로 줄이기 위해 i*M<lcm의 방식을 사용했습니다.

 

(i*M+x-y) % N ==0 이라면 x 값도 나오고 y 값도 나온다는 것을 의미하기 때문에 index를 초기화 시켜준 뒤 break를 걸어주었습니다. 

 

이런 식의 반복문을 사용한다면 반복문의 최대 반복수는 lcm%M 번으로 줄일 수 있습니다.

 

  • 코드

 

import java.io.IOException;
import java.io.InputStream;
import java.util.*;

public class Main {
	static StringBuilder sb;

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		SetData();
		System.out.println(sb);
	}

	private static void SetData() throws Exception {
		InputReader in = new InputReader(System.in);

		int testcase = in.nextInt();
		sb = new StringBuilder();

		for (int i = 0; i < testcase; i++) {
			int M = in.nextInt();
			int N = in.nextInt();
			int x = in.nextInt();
			int y = in.nextInt();
			int lcm = M * N / gcd(M, N);

			sb.append(FindValue(lcm, M, N, x, y)).append("\n");
		}
	}

	private static int gcd(int x, int y) {
		if (x % y == 0)
			return y;

		return gcd(y, x % y);
	}

	private static int FindValue(int lcm, int M, int N, int x, int y) {
		int answer = -1;
		for (int i = 0; i * M < lcm; i++) {
			if ((i * M + x - y) % N == 0) {
				answer = i * M + x;
				break;
			}
		}
		return answer;
	}
}

class InputReader {
	private final InputStream stream;
	private final byte[] buf = new byte[8192];
	private int curChar, snumChars;

	public InputReader(InputStream st) {
		this.stream = st;
	}

	public int read() {
		if (snumChars == -1)
			throw new InputMismatchException();
		if (curChar >= snumChars) {
			curChar = 0;
			try {
				snumChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (snumChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int nextInt() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public long nextLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public int[] nextIntArray(int n) {
		int a[] = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		return a;
	}

	public String nextLine() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isEndOfLine(c));
		return res.toString();
	}

	public boolean isSpaceChar(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	private boolean isEndOfLine(int c) {
		return c == '\n' || c == '\r' || c == -1;
	}
}

+ Recent posts