알고리즘(백준 등) 공부/백준(자바)
백준 1433번: 화학 실험
posite
2026. 4. 28. 12:22
N개의 용액을 섞어서 농도 M% 용액을 최대 몇 리터를 만들 수 있는지 구하는 문제이다.
M%와 같은 농도를 가진 용액은 이미 완성되어 있으므로 최종 리터에 추가한다. 나머지는 두 개의 리스트로 나누어 각각 낮은 농도, 높은 농도 용액을 넣었다.
static class Solution {
int percent, liter, diff;
Solution(int percent, int liter, int m) {
this.percent = percent;
this.liter = liter;
this.diff = Math.abs(percent - m);
}
}
double answer = 0.0;
List<Solution> lowerSolutions = new ArrayList<>(), higherSolutions = new ArrayList<>();
for (int i = 0; i < n; i++) {
st = new StringTokenizer(br.readLine());
int percent = Integer.parseInt(st.nextToken()), liter = Integer.parseInt(st.nextToken());
if (percent == m) {
answer += liter;
} else if (percent > m) {
higherSolutions.add(new Solution(percent, liter, m));
} else {
lowerSolutions.add(new Solution(percent, liter, m));
}
}
최대한 많은 양의 농도 M% 용액을 만들기 위해, M%에 가까운 용액을 섞어야 한다. 이를 위해, 낮은 농도, 높은 농도 용액들의 각각의 최대 가용량을 구하여 최대한 섞을 수 있는 양을 구한 뒤, 농도차이가 적은 순서대로 각각의 리스트를 정렬한다.
double maxPosScore = 0;
for (Solution s : higherSolutions) {
maxPosScore += s.liter * s.diff;
}
double maxNegScore = 0;
for (Solution s : lowerSolutions) {
maxNegScore += s.liter * s.diff;
}
double targetScore = Math.min(maxPosScore, maxNegScore);
Collections.sort(lowerSolutions, Comparator.comparingInt(s -> s.diff));
Collections.sort(higherSolutions, Comparator.comparingInt(s -> s.diff));
이후, 정렬된 리스트 별로 최대한 섞을 수 있는 양에 섞으면서 만들 수 있는 최대 부피를 구한다.
private static double getVolumeToMatchScore(List<Solution> list, double targetScore) {
double currentScore = 0;
double volumeSum = 0;
for (Solution s : list) {
double remainingScore = targetScore - currentScore;
if (remainingScore <= 0) {
break;
}
double potentialScore = (double) s.liter * s.diff;
if (potentialScore <= remainingScore) {
volumeSum += s.liter;
currentScore += potentialScore;
} else {
volumeSum += remainingScore / s.diff;
currentScore = targetScore;
break;
}
}
return volumeSum;
}
결과 코드는 다음과 같다.
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.StringTokenizer;
public class 화학실험1433 {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken()), m = Integer.parseInt(st.nextToken());
double answer = 0.0;
List<Solution> lowerSolutions = new ArrayList<>(), higherSolutions = new ArrayList<>();
for (int i = 0; i < n; i++) {
st = new StringTokenizer(br.readLine());
int percent = Integer.parseInt(st.nextToken()), liter = Integer.parseInt(st.nextToken());
if (percent == m) {
answer += liter;
} else if (percent > m) {
higherSolutions.add(new Solution(percent, liter, m));
} else {
lowerSolutions.add(new Solution(percent, liter, m));
}
}
br.close();
double maxPosScore = 0;
for (Solution s : higherSolutions) {
maxPosScore += s.liter * s.diff;
}
double maxNegScore = 0;
for (Solution s : lowerSolutions) {
maxNegScore += s.liter * s.diff;
}
double targetScore = Math.min(maxPosScore, maxNegScore);
Collections.sort(lowerSolutions, Comparator.comparingInt(s -> s.diff));
Collections.sort(higherSolutions, Comparator.comparingInt(s -> s.diff));
answer += getVolumeToMatchScore(higherSolutions, targetScore);
answer += getVolumeToMatchScore(lowerSolutions, targetScore);
System.out.print(answer);
}
private static double getVolumeToMatchScore(List<Solution> list, double targetScore) {
double currentScore = 0;
double volumeSum = 0;
for (Solution s : list) {
double remainingScore = targetScore - currentScore;
if (remainingScore <= 0) {
break;
}
double potentialScore = (double) s.liter * s.diff;
if (potentialScore <= remainingScore) {
volumeSum += s.liter;
currentScore += potentialScore;
} else {
volumeSum += remainingScore / s.diff;
currentScore = targetScore;
break;
}
}
return volumeSum;
}
static class Solution {
int percent, liter, diff;
Solution(int percent, int liter, int m) {
this.percent = percent;
this.liter = liter;
this.diff = Math.abs(percent - m);
}
}
}