문제 원본 : https://www.acmicpc.net/problem/4781
4781번: 사탕 가게
각 테스트 케이스의 첫째 줄에는 가게에 있는 사탕 종류의 수 n과 상근이가 가지고 있는 돈의 양 m이 주어진다. (1 ≤ n ≤ 5,000, 0.01 ≤ m ≤ 100.00) m은 항상 소수점 둘째자리까지 주어진다. 다음 n개
www.acmicpc.net
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
int n, m, c, p;
int[] cal, price;
int[][] dp;
StringTokenizer st;
StringBuilder builder = new StringBuilder();
while (true) {
String s = br.readLine();
if (s.equals("0 0.00")) {
break;
}
st = new StringTokenizer(s);
n = Integer.parseInt(st.nextToken());
m = (int) (Double.parseDouble(st.nextToken()) * 100 + 0.5);
cal = new int[n + 1];
price = new int[n + 1];
for (int i = 1; i <= n; ++i) {
st = new StringTokenizer(br.readLine());
c = Integer.parseInt(st.nextToken());
p = (int) (Double.parseDouble(st.nextToken()) * 100 + 0.5);
cal[i] = c;
price[i] = p;
}
dp = new int[n + 1][m + 1];
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
if (j - price[i] >= 0) {
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - price[i]] + cal[i]);
} else {
dp[i][j] = dp[i - 1][j];
}
}
}
builder.append(dp[n][m]).append("\n");
}
bw.write(builder.toString());
bw.close();
br.close();
}
}
- 다이내믹 프로그래밍 문제
- DP 알고리즘 중 유명한 0/1 배낭 문제이다.
- 주의할 점은 double형에 100을 곱해 int형으로 변환할 때 0.5를 더해줘야 한다.
- 소수점은 2의 거듭제곱이 아닌 이상 오차가 존재할 수밖에 없기 때문에 0.5를 더해줘야 손실을 방지할 수 있다.
'알고리즘 > BOJ' 카테고리의 다른 글
| [BOJ] 1051. 숫자 정사각형 (0) | 2022.04.10 |
|---|---|
| [BOJ] 3273. 두 수의 합 (0) | 2022.04.09 |
| [BOJ] 5721. 사탕 줍기 대회 (0) | 2022.04.07 |
| [BOJ] 1976. 여행 가자 (0) | 2022.04.06 |
| [BOJ] 2470. 두 용액 (0) | 2022.04.05 |