[문제 설명]

매운 것을 좋아하는 Leo는 모든 음식의 스코빌 지수를 K 이상으로 만들고 싶습니다. 모든 음식의 스코빌 지수를 K 이상으로 만들기 위해 Leo는 스코빌 지수가 가장 낮은 두 개의 음식을 아래와 같이 특별한 방법으로 섞어 새로운 음식을 만듭니다.

섞은 음식의 스코빌 지수 = 가장 맵지 않은 음식의 스코빌 지수 + (두 번째로 맵지 않은 음식의 스코빌 지수 * 2)

Leo는 모든 음식의 스코빌 지수가 K 이상이 될 때까지 반복하여 섞습니다.
Leo가 가진 음식의 스코빌 지수를 담은 배열 scoville과 원하는 스코빌 지수 K가 주어질 때, 모든 음식의 스코빌 지수를 K 이상으로 만들기 위해 섞어야 하는 최소 횟수를 return 하도록 solution 함수를 작성해주세요.

 

<제한 사항>

  • scoville의 길이는 2 이상 1,000,000 이하입니다.
  • K는 0 이상 1,000,000,000 이하입니다.
  • scoville의 원소는 각각 0 이상 1,000,000 이하입니다.
  • 모든 음식의 스코빌 지수를 K 이상으로 만들 수 없는 경우에는 -1을 return 합니다.

입출력 예

scovilleKreturn

[1, 2, 3, 9, 10, 12] 7 2

 

<입출력 예 설명>

  1. 스코빌 지수가 1인 음식과 2인 음식을 섞으면 음식의 스코빌 지수가 아래와 같이 됩니다.
    새로운 음식의 스코빌 지수 = 1 + (2 * 2) = 5
    가진 음식의 스코빌 지수 = [5, 3, 9, 10, 12]
  2. 스코빌 지수가 3인 음식과 5인 음식을 섞으면 음식의 스코빌 지수가 아래와 같이 됩니다.
    새로운 음식의 스코빌 지수 = 3 + (5 * 2) = 13
    가진 음식의 스코빌 지수 = [13, 9, 10, 12]

모든 음식의 스코빌 지수가 7 이상이 되었고 이때 섞은 횟수는 2회입니다.


>문제 풀이

 

변화하는 값에 따라 계속 오름차순을 해야하기 때문에 우선순위 큐를 이용하는게 좋다고 생각해서 Priority Queue를 사용했습니다.

 

<로직>

PriorityQueue<Integer> pq;

int scoville[]=[1, 2, 3, 9, 10, 12];

int K=7;

  1. scoville[]을 pq에 넣어줍니다.
    pq: [1, 2, 3, 9, 10, 12]
  2. 작은값+두번째 작은값 * 2
    1, 2를 pq에서 빼서, 1+ 2*2=5 ->pq.offer(5)
    answer++; //카운팅 해줍니다.
    [5, 3, 9, 10, 12] =>> [3, 5, 9, 10, 12]
  3. pq.poll()>=K 일때까지 반복해줍니다.
  4. 단, 할 수 있는 연산을 다 했는데도 모든 값의 수치를 K이상으로 만들 수 없는 경우에는 answer=-1;

 

>전체 코드

 

import java.util.*;
class Solution {
    public int solution(int[] scoville, int K) {
        int answer = 0, value=0;
        PriorityQueue<Integer> pq= new PriorityQueue<>();
        
        for(int i: scoville){
            pq.offer(i);
        }
        
        while(pq.size()>1){
            if(pq.peek()>=K) break;
            pq.offer(pq.poll()+pq.poll()*2);
            answer++;
        }
        if(pq.poll()<K) answer=-1;
        
        return answer;
    }
}

https://programmers.co.kr/learn/courses/30/lessons/42626#

 

코딩테스트 연습 - 더 맵게

매운 것을 좋아하는 Leo는 모든 음식의 스코빌 지수를 K 이상으로 만들고 싶습니다. 모든 음식의 스코빌 지수를 K 이상으로 만들기 위해 Leo는 스코빌 지수가 가장 낮은 두 개의 음식을 아래와 같

programmers.co.kr

 

[문제]

방향그래프가 주어지면 주어진 시작점에서 다른 모든 정점으로의 최단 경로를 구하는 프로그램을 작성하시오. 단, 모든 간선의 가중치는 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를 출력하면 된다.

 

[예제]

 


>문제 풀이

 

말로만 듣던 다익스트라 알고리즘을 이용하여 풀어보았습니다.

 

*다익스트라 알고리즘을 풀기 위해서는 우선순위 큐에 대해서도 알아야하는데, 오래전에(?) 몇문제 안풀었더니 개념이 잘 기억이 안나더라고요... 그래서 힙 자료구조, 우선순위 큐 부터 공부하고 다익스트라 알고리즘을 이해하느라 좀 오래걸렸습니다.

**공부하기 위해 참고한 링크는(힙, 우선순위 큐, 다익스트라 알고리즘) 글 가장 아래에 달아놓겠습니다.

 

다익스트라 알고리즘은 음의 간선을 포함하지 않을 때 사용할 수 있는데, 이 글에서 가중치 w의 범위가 10 이하의 자연수라고 했으므로 사용 가능합니다.

 

 

main

* 초반에 가중치 값의 배열인 distance[]의 모든 값을 -1로 초기화 해줍니다.

* dijkstra 를 돌리고 나서도 distance[]값이 -1인 정점은 "INF"를 출력해줍니다.

 

dijkstra

우선순위에 시작지점을 offer

시작지점의 가중치 값= 0

 

**우선순위 큐가 빌 때까지 반복

1. 출발 정점에 연결되어 있는 정점들의 가중치 값을 넣어줍니다.

2. 방문한적이 없으면:

  1. 방문처리를 해주고
  2. 현재 정점을 기준으로 연결된 정점들 중에 가중치가 작은 포인트 부터 가중치 값들을 업데이트 해줍니다.
    연결된 정점 i의 가중치 값= min( 정점 i의 가중치 값, 현재 정점의 가중치 값+ 연결된 간선의 가중치 값);
  3. 업데이트 후 정점 i를 우선순위 큐에 넣어줍니다.

 

 

문제를 풀기위해 참고한 글: https://jellyinghead.tistory.com/78

 

 

>전체 코드

 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Main {
	static int distance[];
	static LinkedList<Point> list[];
	static boolean visited[];
	
	public static void main(String [] args) throws IOException {
		int V, E, K, u, v, w;
		BufferedReader br= new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st= new StringTokenizer(br.readLine());
		
		V= Integer.parseInt(st.nextToken());
		E= Integer.parseInt(st.nextToken());
		K= Integer.parseInt(br.readLine());
		
		distance= new int[V+1];
		list= new LinkedList[V+1];
		visited= new boolean[V+1];
		
		Arrays.fill(distance, -1);
		for(int i=1; i<=V; i++) {
			list[i]= new LinkedList<>();
		}
		
		//입력
		for(int i=0; i<E; i++) {
			st = new StringTokenizer(br.readLine());
            u = Integer.parseInt(st.nextToken());
            v = Integer.parseInt(st.nextToken());
            w = Integer.parseInt(st.nextToken());
            list[u].add(new Point(v, w));
		}
		
		dijkstra(K);
		
		//출력
		StringBuilder sb= new StringBuilder();
		
		for(int i=1; i<=V; i++) {
			if(distance[i]==-1) sb.append("INF\n");
			else sb.append(distance[i]+"\n");
		}
		System.out.print(sb.toString());
		br.close();
		
    }//main
	
	public static void dijkstra(int start) {
		PriorityQueue<Point> pq= new PriorityQueue<>();
		Point now;
		
		pq.offer(new Point(start, 0));
		distance[start]=0;
		
		while(!pq.isEmpty()) {
			now= pq.poll();
			
			if(visited[now.end]) continue;
			visited[now.end]= true;
			for(Point next: list[now.end]) {
				if(distance[next.end]==-1||distance[next.end]>distance[now.end] + next.weight) {
					distance[next.end]= distance[now.end] + next.weight;
					pq.offer(new Point(next.end, distance[next.end]));
				}
			}
		}
	}
	
	//정점 클래스
	static	class Point implements Comparable<Point>{
		int end, weight;
			
		public Point(int end, int weight) {
			this.end= end;
			this.weight= weight;
		}
		public int compareTo(Point p) {
			return weight - p.weight;
		}
	}
}

https://www.acmicpc.net/problem/1753

 

1753번: 최단경로

첫째 줄에 정점의 개수 V와 간선의 개수 E가 주어진다. (1≤V≤20,000, 1≤E≤300,000) 모든 정점에는 1부터 V까지 번호가 매겨져 있다고 가정한다. 둘째 줄에는 시작 정점의 번호 K(1≤K≤V)가 주어진다.

www.acmicpc.net

 

 


**참고한 링크)

https://gmlwjd9405.github.io/2018/05/10/data-structure-heap.html

 

[자료구조] 힙(heap)이란 - Heee's Development Blog

Step by step goes a long way.

gmlwjd9405.github.io

https://velog.io/@gillog/Java-Priority-Queue%EC%9A%B0%EC%84%A0-%EC%88%9C%EC%9C%84-%ED%81%90

 

[Java] Priority Queue(우선 순위 큐)

PriorityQueue란 우선순위 큐로써 일반적인 큐의 구조 FIFO(First In First Out)를 가지면서, 데이터가 들어온 순서대로 데이터가 나가는 것이 아닌 우선순위를 먼저 결정하고 그 우선순위가 높은 데이터

velog.io

https://m.blog.naver.com/ndb796/221234424646

 

23. 다익스트라(Dijkstra) 알고리즘

다익스트라(Dijkstra) 알고리즘은 다이나믹 프로그래밍을 활용한 대표적인 최단 경로(Shortest Path) 탐...

blog.naver.com

 

[문제]

상근이는 창고에서 링 N개를 발견했다. 상근이는 각각의 링이 앞에 있는 링과 뒤에 있는 링과 접하도록 바닥에 내려놓았다.

상근이는 첫 번째 링을 돌리기 시작했고, 나머지 링도 같이 돌아간다는 사실을 발견했다. 나머지 링은 첫 번째 링 보다 빠르게 돌아가기도 했고, 느리게 돌아가기도 했다. 이렇게 링을 돌리다 보니 첫 번째 링을 한 바퀴 돌리면, 나머지 링은 몇 바퀴 도는지 궁금해졌다.

링의 반지름이 주어진다. 이때, 첫 번째 링을 한 바퀴 돌리면, 나머지 링은 몇 바퀴 돌아가는지 구하는 프로그램을 작성하시오.

 

[입력]

첫째 줄에 링의 개수 N이 주어진다. (3 ≤ N ≤ 100)

다음 줄에는 링의 반지름이 상근이가 바닥에 놓은 순서대로 주어진다. 반지름은 1과 1000를 포함하는 사이의 자연수이다.

 

[출력]

출력은 총 N-1줄을 해야 한다. 첫 번째 링을 제외한 각각의 링에 대해서, 첫 번째 링을 한 바퀴 돌리면 그 링은 몇 바퀴 도는지 기약 분수 형태 A/B로 출력한다.

 

[예제]


>문제 풀이

최대공약수로 나눠서 기약분수를 출력해주면 됩니다.

 

>전체 코드

 

import java.util.*;

public class Main {
	
	public static void main(String [] args) {
		int N, gcd, arr[][];
		
		Scanner scan= new Scanner(System.in);
		
		N= scan.nextInt();
		arr= new int[N][2];
		
		arr[0][0]= scan.nextInt();
		for(int i=1; i<N; i++) {
			arr[i][0]= scan.nextInt();
			gcd=gcd(arr[0][0], arr[i][0]);
			arr[i][0]/=gcd; //분자
			arr[i][1]=arr[0][0]/gcd; //분모
		}
		
		for(int i=1; i<N; i++) {
			System.out.println(arr[i][1]+"/"+arr[i][0]);
		}
    }//main
	
	public static int gcd(int a, int b) {
		int mod;
		
		mod=a>b?a%b:b%a;
		if(mod==0) {
			return a<b?a:b;
		}
		return gcd(a<b?a:b, mod);
	}
}

https://www.acmicpc.net/problem/3036

 

3036번: 링

출력은 총 N-1줄을 해야 한다. 첫 번째 링을 제외한 각각의 링에 대해서, 첫 번째 링을 한 바퀴 돌리면 그 링은 몇 바퀴 도는지 기약 분수 형태 A/B로 출력한다.

www.acmicpc.net

 

[문제]

피보나치 비스무리한 수열은 f(n) = f(n-1) + f(n-3)인 수열이다. f(1) = f(2) = f(3) = 1이며 피보나치 비스무리한 수열을 나열하면 다음과 같다.

1, 1, 1, 2, 3, 4, 6, 9, 13, 19, ...

자연수 n을 입력받아 n번째 피보나치 비스무리한 수열을 구해보자!

 

[입력]

자연수 n(1<=n<=116)이 주어진다.

 

[출력]

n번째 피보나치 비스무리한 수를 출력한다.

 

[예제]

 


>문제 풀이

 

 

 예전에 틀렸던 문제가 몇 개 있길래 뭘 틀렸나 싶어서 다시 풀어보려고 한다.

오늘 문제는 쉬웠었는데, 아마 풀다가 말았던게 아닌가 싶다.

 

arr[1], arr[2], arr[3]=1 미리 넣어주고(단 입력값에 따라 대입 처리를 해줘야한다.)

arr[i]= arr[i-3]+arr[i-1]; 을 for문 돌려주면 된다.

 

 

>전체 코드

 

import java.util.*;

public class Main {
	
	public static void main(String [] args) {
		int N;
		long arr[];
		
		Scanner scan= new Scanner(System.in);
		
		N= scan.nextInt();
		arr= new long[N+1];
		
		arr[1]=1;
		if(N>1) arr[2]=1;
		if(N>2) arr[3]=1;
		for(int i=4; i<=N; i++) {
			arr[i]=arr[i-3]+arr[i-1];
		}
		
		System.out.println(arr[N]);
        
    }//main	
}

https://www.acmicpc.net/problem/14495

 

14495번: 피보나치 비스무리한 수열

피보나치 비스무리한 수열은 f(n) = f(n-1) + f(n-3)인 수열이다. f(1) = f(2) = f(3) = 1이며 피보나치 비스무리한 수열을 나열하면 다음과 같다. 1, 1, 1, 2, 3, 4, 6, 9, 13, 19, ... 자연수 n을 입력받아 n번째 피보

www.acmicpc.net

 

[문제]

수직선 위에 N개의 좌표 X1, X2, ..., XN이 있다. 이 좌표에 좌표 압축을 적용하려고 한다.

Xi를 좌표 압축한 결과 X'i의 값은 Xi > Xj를 만족하는 서로 다른 좌표의 개수와 같아야 한다.

X1, X2, ..., XN에 좌표 압축을 적용한 결과 X'1, X'2, ..., X'N를 출력해보자.

 

[입력]

첫째 줄에 N이 주어진다.

둘째 줄에는 공백 한 칸으로 구분된 X1, X2, ..., XN이 주어진다.

 

[출력]

첫째 줄에 X'1, X'2, ..., X'N을 공백 한 칸으로 구분해서 출력한다.

 

[제한]

  • 1 ≤ N ≤ 1,000,000
  • -109 ≤ Xi ≤ 109

 

[예제]


>문제 풀이

 

정렬하는 방법과 hashmap 사용할 줄만 알면 쉬운 문제였다.

(근데 hashmap 딱 한번 써보고 안써서 까먹어서 다시 찾아봄..ㅎㅎ;)

 

<로직>

  1. N, arr[] 입력 받고
  2. arr_v= arr.clone(); // arr_v[] 배열에다가 깊은 복사로 붙여넣는다.
  3. arr.sort
  4. N만큼 반복문을 돌리며
    : arr값을 중복되지 않게 hashmap에 넣는다.
  5. N만큼 반복문을 돌리며
    : StringBuilder sb에다가 hashmap에서 키값이 arr_v인 value를 붙여준다.(append)
  6. sb.toString()을 출력한다.

 

 

 

>전체 코드

 

import java.util.*;

public class Main {
	
	public static void main(String [] args) {
		int N, before, arr[], arr_v[];
		
		Scanner scan= new Scanner(System.in);
		
                //입력받기
		N= scan.nextInt();
		arr= new int[N];
		arr_v= new int[N];
		HashMap<Integer, Integer> map= new HashMap<>();
		
		for(int i=0; i<N; i++) {
			arr[i]= scan.nextInt();
		}
        
		arr_v= arr.clone(); //arr를 arr_v로 (깊은)복사
		Arrays.sort(arr); //정렬
		
		before= (int)Math.pow(10, 9)+1;
		for(int i=0, j=0; i<N; i++) {
			if(before!=arr[i]) { //중복아닌 값만
				map.put(arr[i], j++);//map에 저장
				before=arr[i];
			}
		}
		
		StringBuilder sb= new StringBuilder();
		for(int i=0; i<N; i++) {
			sb.append(map.get(arr_v[i])+" "); //arr_v값을 키로 가진 map을 get
		}
		System.out.println(sb.toString()); //출력~~
		
    }//end	
}

https://www.acmicpc.net/problem/18870

 

18870번: 좌표 압축

수직선 위에 N개의 좌표 X1, X2, ..., XN이 있다. 이 좌표에 좌표 압축을 적용하려고 한다. Xi를 좌표 압축한 결과 X'i의 값은 Xi > Xj를 만족하는 서로 다른 좌표의 개수와 같아야 한다. X1, X2, ..., XN에 좌

www.acmicpc.net

 

+ Recent posts