문제

방향그래프가 주어지면 주어진 시작점에서 다른 모든 정점으로의 최단 경로를 구하는 프로그램을 작성하시오. 단, 모든 간선의 가중치는 10 이하의 자연수이다.

 

입력

첫째 줄에 정점의 개수 V와 간선의 개수 E가 주어진다. (1 ≤ V ≤ 20,000, 1 ≤ E ≤ 300,000) 모든 정점에는 1부터 V까지 번호가 매겨져 있다고 가정한다. 둘째 줄에는 시작 정점의 번호 K(1 ≤ K ≤ V)가 주어진다. 셋째 줄부터 E개의 줄에 걸쳐 각 간선을 나타내는 세 개의 정수 (u, v, w)가 순서대로 주어진다. 이는 u에서 v로 가는 가중치 w인 간선이 존재한다는 뜻이다. u와 v는 서로 다르며 w는 10 이하의 자연수이다. 서로 다른 두 정점 사이에 여러 개의 간선이 존재할 수도 있음에 유의한다.

출력

첫째 줄부터 V개의 줄에 걸쳐, i번째 줄에 i번 정점으로의 최단 경로의 경로값을 출력한다. 시작점 자신은 0으로 출력하고, 경로가 존재하지 않는 경우에는 INF를 출력하면 된다.

예제 입력 1 

5 6
1
5 1 1
1 2 2
1 3 3
2 3 4
2 4 5
3 4 6

예제 출력 1 

0
2
3
7
INF

 

문제접근

단방향 그래프 최단경로 찾기 문제이다. 다익스트라 알고리즘을 이용하여 문제를 해결하자.

  1. 간선 정보를 저장할 Node 클라스 작성.
  2. 간선 정보들을 저장할 graph와 각 정점의 비용을 저장할 dist를 선언한다.
  3. 간선 정보 graph에 추가
  4. 다익스트라로 비용을 저장한다.
    1. 우선순위 큐에 시작 노드를 add한다.
    2. loop를 돌며 우선순위 큐에서 해당 노드를 poll한다.
    3. poll한 노드의 다음 노드가 이미 탐색한 경로면 pass
    4. poll한 노드가 다음 노드가 탐색하지 않은 노드인 경우 도착점의 가중치가 더적은경우 최신화 하고 해당 노드와 최적경로를 add.

문제풀이

public class Main {

	static int v, e, k; // 정점 갯수, 간선 갯수, 시작 정점
	static List<List<Node>> graph; // #2
	static int[] dist;

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

		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

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

		v = Integer.parseInt(st.nextToken());
		e = Integer.parseInt(st.nextToken());
		k = Integer.parseInt(br.readLine());

		graph = new ArrayList<>();
		for (int i = 0; i < v + 1; i++) {
			graph.add(new ArrayList<Node>());
		}

		dist = new int[v + 1];
		Arrays.fill(dist, Integer.MAX_VALUE);

		for (int i = 0; i < e; i++) { // #3
			st = new StringTokenizer(br.readLine());

			int start, end, weight;

			start = Integer.parseInt(st.nextToken());
			end = Integer.parseInt(st.nextToken());
			weight = Integer.parseInt(st.nextToken());

			graph.get(start).add(new Node(end, weight));
		}

		/*
		 * graph 정보 확인하기 int gIdx = 0; for(List<Node> l : graph) {
		 * System.out.print(gIdx++ + " ["); for(Node n : l) { System.out.print(n +
		 * "\t"); } System.out.println("]"); }
		 */
		
		dijkstra(k);

		for (int i = 0; i<dist.length; i++) {
			if(i == 0) continue;
			
			if(dist[i] == Integer.MAX_VALUE) {
				bw.write("INF" + "\n");
			}else {
				bw.write(dist[i] + "\n");
			}
		}
		bw.flush();
		br.close();
		bw.close();
	}

	public static void dijkstra(int start) {
		PriorityQueue<Node> pq = new PriorityQueue<>();
		boolean[] check = new boolean[v + 1];
		pq.add(new Node(start, 0));					// #4.1
		dist[start] = 0;

		while (!pq.isEmpty()) {						// #4.2
			Node curNode = pq.poll();
			int cur = curNode.to;					// 다음 경로 노드를 현재노드로 변경

			if (check[cur] == true)
				continue; 							// #4.3 다음 경로 노드 이미 탐색한 노드면 pass
			check[cur] = true;						// 현재 모드 확인 true

			
			for (Node node : graph.get(cur)) { 		// 현재 노드의 다음 경로 확인
				//System.out.println(cur + "->" + node.to);
				if (dist[node.to] > dist[cur] + node.weight) {	//#4.4 현재 경로 + 다음경로 비용 기존 비용보다 더 적게드는 경우
					int newDist = dist[cur] + node.weight;	// 다음경로 비용 최신화
					dist[node.to] = newDist;
					pq.add(new Node(node.to, newDist));	// 다음경로 , 최적 비용으로 que add
				}
			}
		}

	}

}

class Node implements Comparable<Node> { // #1
	int to;
	int weight;

	Node(int to, int weight) {
		this.to = to;
		this.weight = weight;
	}

	@Override
	public int compareTo(Node o) {
		return weight - o.weight;
	}

	@Override
	public String toString() {
		return "to - " + to + " weight" + weight;
	}
}

'Study > BOJ - 풀이' 카테고리의 다른 글

백준 - 24479 (Java)  (2259) 2023.09.28
백준 - 11399 (Java)  (2249) 2023.09.27
백준 - 1541 (Java)  (2246) 2023.09.27
백준 - 12891 (Java)  (2238) 2023.09.27
백준 - 12847 (Java)  (2257) 2023.09.27

문제

인하은행에는 ATM이 1대밖에 없다. 지금 이 ATM앞에 N명의 사람들이 줄을 서있다. 사람은 1번부터 N번까지 번호가 매겨져 있으며, i번 사람이 돈을 인출하는데 걸리는 시간은 Pi분이다.

사람들이 줄을 서는 순서에 따라서, 돈을 인출하는데 필요한 시간의 합이 달라지게 된다. 예를 들어, 총 5명이 있고, P1 = 3, P2 = 1, P3 = 4, P4 = 3, P5 = 2 인 경우를 생각해보자. [1, 2, 3, 4, 5] 순서로 줄을 선다면, 1번 사람은 3분만에 돈을 뽑을 수 있다. 2번 사람은 1번 사람이 돈을 뽑을 때 까지 기다려야 하기 때문에, 3+1 = 4분이 걸리게 된다. 3번 사람은 1번, 2번 사람이 돈을 뽑을 때까지 기다려야 하기 때문에, 총 3+1+4 = 8분이 필요하게 된다. 4번 사람은 3+1+4+3 = 11분, 5번 사람은 3+1+4+3+2 = 13분이 걸리게 된다. 이 경우에 각 사람이 돈을 인출하는데 필요한 시간의 합은 3+4+8+11+13 = 39분이 된다.

줄을 [2, 5, 1, 4, 3] 순서로 줄을 서면, 2번 사람은 1분만에, 5번 사람은 1+2 = 3분, 1번 사람은 1+2+3 = 6분, 4번 사람은 1+2+3+3 = 9분, 3번 사람은 1+2+3+3+4 = 13분이 걸리게 된다. 각 사람이 돈을 인출하는데 필요한 시간의 합은 1+3+6+9+13 = 32분이다. 이 방법보다 더 필요한 시간의 합을 최소로 만들 수는 없다.

줄을 서 있는 사람의 수 N과 각 사람이 돈을 인출하는데 걸리는 시간 Pi가 주어졌을 때, 각 사람이 돈을 인출하는데 필요한 시간의 합의 최솟값을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 사람의 수 N(1 ≤ N ≤ 1,000)이 주어진다. 둘째 줄에는 각 사람이 돈을 인출하는데 걸리는 시간 Pi가 주어진다. (1 ≤ Pi ≤ 1,000)

출력

첫째 줄에 각 사람이 돈을 인출하는데 필요한 시간의 합의 최솟값을 출력한다.

예제 입력 1 

5
3 1 4 3 2

예제 출력 1 

32

 

문제접근

돈 인출하는데 걸리는 시간이 가장 적은 사람부터 줄을 세워야 대기시간을 최소화 할 수있다.

1. 소요시간을 오름차순으로 정렬한다.

2. 소요시간을 계산한다. 돈 뽑는시간 * (인출자 + 대기인원)

 

문제풀이

public class Main{

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

		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
		
		
		int N = Integer.parseInt(br.readLine());
		
		StringTokenizer st;
		st = new StringTokenizer(br.readLine());

		int[] arr = new int[N];
		for(int i = 0; i < N; i++)
			arr[i] = Integer.parseInt(st.nextToken());
		
		Arrays.sort(arr);				// #1
		
		int sum = 0;
		for(int i = N; i > 0; i--) {	//#2
			sum += arr[N - i] * i;
		}
		
		bw.write(sum + "");
		
		bw.flush();
		br.close();
		bw.close();
		
	}

}

 

'Study > BOJ - 풀이' 카테고리의 다른 글

백준 - 24479 (Java)  (2259) 2023.09.28
백준 - 1753 (Java)  (2574) 2023.09.28
백준 - 1541 (Java)  (2246) 2023.09.27
백준 - 12891 (Java)  (2238) 2023.09.27
백준 - 12847 (Java)  (2257) 2023.09.27

문제

세준이는 양수와 +, -, 그리고 괄호를 가지고 식을 만들었다. 그리고 나서 세준이는 괄호를 모두 지웠다.

그리고 나서 세준이는 괄호를 적절히 쳐서 이 식의 값을 최소로 만들려고 한다.

괄호를 적절히 쳐서 이 식의 값을 최소로 만드는 프로그램을 작성하시오.

입력

첫째 줄에 식이 주어진다. 식은 ‘0’~‘9’, ‘+’, 그리고 ‘-’만으로 이루어져 있고, 가장 처음과 마지막 문자는 숫자이다. 그리고 연속해서 두 개 이상의 연산자가 나타나지 않고, 5자리보다 많이 연속되는 숫자는 없다. 수는 0으로 시작할 수 있다. 입력으로 주어지는 식의 길이는 50보다 작거나 같다.

출력

첫째 줄에 정답을 출력한다.

예제 입력 1 

55-50+40

예제 출력 1 

-35

예제 입력 2 

10+20+30+40

예제 출력 2 

100

예제 입력 3 

00009-00009

예제 출력 3 

0

 

문제접근

 +를 이용하여 최대한 큰 값을 만들고 이전값에서 빼주는것이 좋을것 같다.

  1.  수식을 stack 에 숫자/연산자로 나누어 차례대로 push한다.
  2. loop를 돌며 다음을 실행한다.
  3.  - 가 나올때까지 숫자를 임시값에 더한다.
  4.  - 가 나오면 연산된 수를 결과값에서 빼주고 임시값을 초기화한다.
  5.  loop가 끝난 후 임시값을 결과값에 더한다.

문제풀이

public class Main {

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

		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
		
		String str = br.readLine();
		
		Stack<String> stack = new Stack<>();
		
		

		int tempIdx = 0;
		
		for(int i = 0 ; i < str.length(); i++) {					// #1
			if(str.charAt(i) == '+' || str.charAt(i) == '-') {
				stack.add(str.substring(tempIdx,i));
				stack.add(str.substring(i,i+1));
				tempIdx = i+1;
			}
		}
		stack.add(str.substring(tempIdx));
		
		/*
		for(String s : stack) {
			System.out.println(s);
		}
		*/
		
		int answer = 0;
		
		int sum = 0;
		
		while(!stack.isEmpty()) {					// #2
			String temp = stack.pop();
			
			if(temp.equals("+")) {
				continue;
			}else if(temp.equals("-" )){			// #3
				answer -= sum;
				sum = 0;
			}else {
				sum += Integer.parseInt(temp);		// #4
			}
			//System.out.println(sum);
		}
		
		answer += sum;								// #5
		
		
		bw.write(answer + "");
		bw.flush();
		br.close();
		bw.close();
		
		
	}

}

'Study > BOJ - 풀이' 카테고리의 다른 글

백준 - 1753 (Java)  (2574) 2023.09.28
백준 - 11399 (Java)  (2249) 2023.09.27
백준 - 12891 (Java)  (2238) 2023.09.27
백준 - 12847 (Java)  (2257) 2023.09.27
백준 - 2470 (Java)  (1648) 2023.09.26

문제

평소에 문자열을 가지고 노는 것을 좋아하는 민호는 DNA 문자열을 알게 되었다. DNA 문자열은 모든 문자열에 등장하는 문자가 {‘A’, ‘C’, ‘G’, ‘T’} 인 문자열을 말한다. 예를 들어 “ACKA”는 DNA 문자열이 아니지만 “ACCA”는 DNA 문자열이다. 이런 신비한 문자열에 완전히 매료된 민호는 임의의 DNA 문자열을 만들고 만들어진 DNA 문자열의 부분문자열을 비밀번호로 사용하기로 마음먹었다.

하지만 민호는 이러한 방법에는 큰 문제가 있다는 것을 발견했다. 임의의 DNA 문자열의 부분문자열을 뽑았을 때 “AAAA”와 같이 보안에 취약한 비밀번호가 만들어 질 수 있기 때문이다. 그래서 민호는 부분문자열에서 등장하는 문자의 개수가 특정 개수 이상이여야 비밀번호로 사용할 수 있다는 규칙을 만들었다.

임의의 DNA문자열이 “AAACCTGCCAA” 이고 민호가 뽑을 부분문자열의 길이를 4라고 하자. 그리고 부분문자열에 ‘A’ 는 1개 이상, ‘C’는 1개 이상, ‘G’는 1개 이상, ‘T’는 0개 이상이 등장해야 비밀번호로 사용할 수 있다고 하자. 이때 “ACCT” 는 ‘G’ 가 1 개 이상 등장해야 한다는 조건을 만족하지 못해 비밀번호로 사용하지 못한다. 하지만 “GCCA” 은 모든 조건을 만족하기 때문에 비밀번호로 사용할 수 있다.

민호가 만든 임의의 DNA 문자열과 비밀번호로 사용할 부분분자열의 길이, 그리고 {‘A’, ‘C’, ‘G’, ‘T’} 가 각각 몇번 이상 등장해야 비밀번호로 사용할 수 있는지 순서대로 주어졌을 때 민호가 만들 수 있는 비밀번호의 종류의 수를 구하는 프로그램을 작성하자. 단 부분문자열이 등장하는 위치가 다르다면 부분문자열이 같다고 하더라도 다른 문자열로 취급한다.

입력

첫 번째 줄에 민호가 임의로 만든 DNA 문자열 길이 |S|와 비밀번호로 사용할 부분문자열의 길이 |P| 가 주어진다. (1 ≤ |P| ≤ |S| ≤ 1,000,000)

두번 째 줄에는 민호가 임의로 만든 DNA 문자열이 주어진다.

세번 째 줄에는 부분문자열에 포함되어야 할 {‘A’, ‘C’, ‘G’, ‘T’} 의 최소 개수가 공백을 구분으로 주어진다. 각각의 수는 |S| 보다 작거나 같은 음이 아닌 정수이며 총 합은 |S| 보다 작거나 같음이 보장된다.

출력

첫 번째 줄에 민호가 만들 수 있는 비밀번호의 종류의 수를 출력해라.

예제 입력 1 

9 8
CCTGGATTG
2 0 1 1

예제 출력 1

0

예제 입력 2

4 2
GATA
1 0 0 1

 

예제 출력 2

2

 

문제 접근

(+)조건의 일치여부는 HashMap에 문자열의 빈도수를 이용하여 확인한다 -- isValid().

  1. 인덱스 0 부터 인덱스 S-P 까지 loop를 돈다.
  2. 인덱스가 0인 경우 str(0,P) 까지 조건이 일치하는지 확인한다.
  3. 인덱스가 0이 아닌 경우 str(i, i+P) 까지 조건이 일치하는지 확인한다.
    (idx-1의 문자열 빈도수를 감소시키고 , i+P의 문자열의 빈도수를 증가시킨다)
  4. 일치하는 빈도수를 확인한다.

문제풀이

public class Main {

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

		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
		
		StringTokenizer st;
		st = new StringTokenizer(br.readLine());
		
		int S = Integer.parseInt(st.nextToken());
		int P = Integer.parseInt(st.nextToken());
		
		String str = br.readLine();
		
		st = new StringTokenizer(br.readLine());
		
		int answer = 0;
		
		HashMap<Character, Integer> hm = new HashMap<>();
		hm.put('A', Integer.parseInt(st.nextToken()));
		hm.put('C', Integer.parseInt(st.nextToken()));
		hm.put('G', Integer.parseInt(st.nextToken()));
		hm.put('T', Integer.parseInt(st.nextToken()));
		
		char c, prev, next;
		for(int idx = 0 ; idx < S - P + 1; idx++) {		// #1
			if(idx == 0) {								// #2
				for(int i = 0; i < P; i++) {
					c = str.charAt(i);
					hm.put(c ,hm.get(c) -1);
				}
			}else {										// #3
				prev = str.charAt(idx-1);
				hm.put(prev, hm.get(prev) + 1);
				next = str.charAt(idx + P - 1);
				hm.put(next, hm.get(next) - 1);
			}
			
			answer += isValid(hm);						// #4
		}
		bw.write(answer + "");
		
		bw.flush();
		br.close();
		bw.close();
	}
	
	public static int isValid(HashMap<Character, Integer> hm) {
		
		for(Character c : hm.keySet()) {
			if(hm.get(c) > 0) 
				return 0;
		}
		return 1;
	}

}

 

'Study > BOJ - 풀이' 카테고리의 다른 글

백준 - 11399 (Java)  (2249) 2023.09.27
백준 - 1541 (Java)  (2246) 2023.09.27
백준 - 12847 (Java)  (2257) 2023.09.27
백준 - 2470 (Java)  (1648) 2023.09.26
백준 - 3273 (Java)  (1629) 2023.09.26

+ Recent posts