CodingTEST
[백준 1033] 칵테일 (JAVA)
경걍
2023. 8. 17. 21:13
반응형
백준 1033번 문제 - 칵테일
1033번: 칵테일
august14는 세상에서 가장 맛있는 칵테일이다. 이 칵테일을 만드는 정확한 방법은 아직 세상에 공개되지 않았지만, 들어가는 재료 N개는 공개되어 있다. 경근이는 인터넷 검색을 통해서 재료 쌍 N
www.acmicpc.net
문제 분석
- N개의 수와 N-1개의 비율을 입력받고, 그들을 통해 구해진 N개의 최소 배율을 출력해라
- N-1개의 비율 입력(a,b,p,q) : a/b = q/p
해결 키 포인트
- 유클리드 호제법을 이용해 최대 공약수,최소 공배수를 구한다
- 최소 공배수: DFS를 설정하기 시작할 때, 이용
- 비율(분자, 분모)의 최소 공배수의 곱을 초기값으로 - 최대 공약수: 최소 배율을 출력해야하므로, 모든 배율 값의 최대 공약수를 구해 이용
- 최소 공배수: DFS를 설정하기 시작할 때, 이용
- DFS 사용해서 N개 다 설정
- 비율을 저장할 수 있는 class 제작
너무 어려웠음........
유클리드 호제법
MOD연산을 이용해 두 수의 최대 공약수를 구하는 알고리즘이다.
MOD 연산 : 두 값을 나눈 나머지를 구하는 연산
ex. 10 MOD 4 = 2 (10 % 4 = 2)
유클리드 호제법 알고리즘
1. 큰 수를 작은 수로 나누는 MOD 연산 수행
2. 앞 단계에서의 작은 수와 MOD 연산 결과 값(나머지)으로 MOD 연산 수행
3. 나머지가 0이 되는 순간의 작은 수를 최대 공약수로 선택
코드
import java.io.*;
import java.util.*;
public class Main {
static boolean[] isCheckRatio; // 확인했는지 아는 변수
static ArrayList<Ratio> [] ratios; // 비율 값을 알려주는 변수
static long [] realRatio; // 실제 필요한 비율에 따른 최소 값 변수
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
// N 입력
int N = Integer.parseInt(br.readLine());
// 변수 초기화
isCheckRatio = new boolean[N];
ratios = new ArrayList[N];
realRatio = new long[N];
for(int i=0;i<N;i++) {
ratios[i] = new ArrayList<>();
}
// (비율들의) 최소공배수
long lcm = 1;
// N-1개의 재료 조합 입력
for(int i=0;i<N-1;i++) {
// 각 재료의 비율 입력 (a의 질량 / b의 질량 = p/q)
StringTokenizer st = new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
long p = Long.parseLong(st.nextToken());
long q = Long.parseLong(st.nextToken());
// 변수에 추가
ratios[a].add(new Ratio(b, p, q));
ratios[b].add(new Ratio(a, q, p));
// 비율의 최소 공배수를 모두 곱한다.
lcm *= (p * q / GCD(p,q));
}
// 실제 변수 값 초기화
realRatio[0] = lcm;
// DFS로 실제 값 구하기
DFS(0);
// 최대 공약수 구하기
long mgcd = realRatio[0];
for(int i=0;i<N;i++) {
mgcd = GCD(mgcd, realRatio[i]);
}
// 출력
for(int i=0;i<N;i++) {
bw.write(realRatio[i]/mgcd + " ");
}
bw.flush();
bw.close();
}
public static class Ratio {
public int opponent;
public long p;
public long q;
public Ratio(int opponent, long p, long q) {
this.opponent = opponent;
this.p = p;
this.q = q;
}
}
public static long GCD(long a, long b) {
if(b == 0) return a;
return GCD(b, a%b);
}
public static void DFS(int index) {
isCheckRatio[index] = true;
ArrayList<Ratio> ratio = ratios[index];
for(int i=0;i<ratio.size();i++) {
Ratio next = ratio.get(i);
if(!isCheckRatio[next.opponent]) {
realRatio[next.opponent] = realRatio[index] * next.q / next.p;
DFS(next.opponent);
}
}
}
}
반응형