BOJ_12865 평범한 배낭
- TOC {:toc}
이 글은 백준 온라인 저지의 12865번 문제를 풀이한 것을 모아놓은 글입니다.
일종의 연습 기록이며 제가 정답을 받은 코드와 참고할만한 다른 코드를 같이 기록합니다. 필요한 경우 코드에 대한 해설을 기록합니다만 코드는 통과했어도 해설은 틀릴 수 있기 때문에 가볍게 참고해주시길 부탁드립니다. 피드백은 편하신 방법으로 자유롭게 주시면 감사하겠습니다.
2021.05.06 (Python)
메모리 | 시간 | 코드 길이 |
---|---|---|
225444 KB | 5620 ms | 371 B |
단계 | 시작 시각 | 끝난 시각 | 걸린 시간 |
---|---|---|---|
문제 이해 | 23:41:32 | 23:42:16 | |
풀이 생각 1 | 23:43:23 | 23:51:50 | |
풀이 생각 2 | 11:45:36 | 11:58:02 | |
코딩 | 11:58:10 | 12:06:43 | |
디버깅 | 12:07:54 | 12:42:57 |
import sys
input = lambda: sys.stdin.readline().rstrip()
N, K = map(int, input().split())
Vs = [[0] * (K + 1) for _ in range(N)]
for i in range(N):
W, V = map(int, input().split())
for j in range(1, K + 1):
if j < W:
Vs[i][j] = Vs[i - 1][j]
else:
Vs[i][j] = max(Vs[i - 1][j], Vs[i - 1][j - W] + V)
print(Vs[N - 1][K])
아이디어 & 풀이
1부터 K까지 각 무게에서 들 수 있을는 최대 가치합을 저장한다.
W | V | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|---|
6 | 13 | 0 | 0 | 0 | 0 | 0 | 13 | 13 |
4 | 8 | 0 | 0 | 0 | 8 | 8 | 13 | 13 |
3 | 6 | 0 | 6 | 6 | 8 | 8 | 13 | 14 |
5 | 12 | 0 | 6 | 6 | 8 | 12 | 13 | 14 |
-
W
를 인덱스로, 최대 가치 합V
를 값으로 갖는 리스트를 구성한다. -
입력받은
W
보다 큰 W값에 대해서 V를 비교하면서 입력한V
가 더 크면 교체한다.for i > W: V vs F[i] vs F[i-W] + V
디버그
- 각 원소가 바로바로 변하니까 이전 단계를 별도로 저장해주어야 한다.
Vs[3]
의 값을 앞에서 변경하고Vs[7]
의 값을 정할 때Vs[3] + Vs[4]
를 비교하면Vs[3]
은 변한 상태이므로 제대로 된 최댓값을 계산할 수 없다.- 현재 상태에서 이전의
Vs
값들을 유지하려면 이를 별도로 저장해주어야 한다. Vs
를 이차원 배열로 초기화하고 업데이트 때마다 다음 배열에 저장한다.
피드백
max
를 계산할 때Vs[i - 1]
에V
를 더한 값이 항상V
보다 크거나 같기 때문에V
는 고려할 필요가 없다.- 마지막에
Vs
의max
를 계산하지 않고K
를 출력하는게 더 빠르다. (어차피K
의 값이 최댓값이다)
2022.04.03 (JS)
메모리 | 시간 | 코드 길이 |
---|---|---|
200692 KB | 1192 ms | 694 B |
단계 | 시작 시각 | 끝난 시각 | 걸린 시간 |
---|---|---|---|
문제 이해 | 17:47:17 | 17:48:18 | |
풀이 생각 | 16:09:42 | 16:16:05 | |
코딩 | 16:16:07 | 16:39:49 | |
디버깅 | 17:26:03 | 17:30:13 |
const fs = require("fs");
const input = fs.readFileSync('/dev/stdin').toString().trim().split("\n");
const [NK, ...items] = input;
const [N, K] = NK.split(" ").map(Number);
bag = { 0: 0 }; // weight: value
function main() {
const new_bag = { 0: 0 };
items.forEach((item) => {
const [W, V] = item.split(" ").map(Number);
for (let [w, v] of Object.entries(bag)) {
w = parseInt(w);
if (w + W <= K) {
if (bag[w + W]) new_bag[w + W] = Math.max(bag[w + W], v + V);
else new_bag[w + W] = v + V;
}
}
bag = new_bag;
});
return Math.max(...Object.values(bag));
}
console.log(main());
디버그
- 또 입력받을 때
trim()
안 적어서 틀렸다.
피드백
input
입력 받을 때 아예map
으로 전부 다 숫자로 변환하고 하는 게 깔끔했을 것 같다.
참고 답안 1
import sys
input = sys.stdin.readline
N, K = map(int, input().split())
KnapSack = {0: 0}
for _ in range(N):
W, V = map(int, input().split())
tmp = {}
# KanpSack(배낭) 딕셔너리 안의 각 key(무게, w)와 value(가치, v)에 대해서
for w, v in KnapSack.items():
# 현재 아이템과 입력받은 무게의 합(w + W)이 K를 넘지 않고
# 현재 아이템과 입력받은 가치의 합(v + V)이 두 무게를 합친 것의 가치 최댓값(KanpSack[w + W])보다 크면
if w + W <= K and v + V > KnapSack.get(w + W, 0):
# tmp에 해당 무게의 가치 최댓값을 현재 값으로 지정한다.
tmp[w + W] = v + V
# KnapSack을 tmp로 업데이트한다.
KnapSack.update(tmp)
# KnapSack의 value(가치) 중에서 최댓값을 출력한다.
print(max(KnapSack.values()))
아이디어 & 풀이
기본적인 과정은 위의 답과 비슷하다.
리스트 대신 딕셔너리를 사용해 현재 KanpSack
안에 존재하는 아이템에 대해서만 계산한다. 반복을 최소화할 수 있다.
get
의 디폴트 값을 이용해 해당 값을 가져오지 못하면 0을 가져오도록 한다.- 02-5 딕셔너리 자료형: Key로 Value얻기(get) by 점프 투 파이썬
- get() by Python Documentation
변하는 부분만 tmp
를 먼저 구성한 뒤 tmp
로 기존의 KanpSack
을 업데이트해서 사용하는 메모리를 최소화한다.
- 25.1 딕셔너리 조작하기 by 코딩도장
- update() by Python Documentation
참고 답안 2
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin").trim().split("\n");
const bag = input.map((str) => str.split(" ").map(Number));
const [N, K] = bag.shift();
function solution() {
const matrix = Array(K + 1).fill(0);
bag.forEach(([w, v]) => {
for (let i = K; i >= w; i -= 1) {
matrix[i] = Math.max(matrix[i], matrix[i - w] + v);
}
});
return matrix[K];
}
console.log(solution());
풀이 분석해서 적기
-
ps-python ps-js draft