본문 바로가기

Algorithm/백준

[백준] 12865번: 평범한 배낭

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

 

12865번: 평범한 배낭

첫 줄에 물품의 수 N(1 ≤ N ≤ 100)과 준서가 버틸 수 있는 무게 K(1 ≤ K ≤ 100,000)가 주어진다. 두 번째 줄부터 N개의 줄에 거쳐 각 물건의 무게 W(1 ≤ W ≤ 100,000)와 해당 물건의 가치 V(0 ≤ V ≤ 1,000)가 주어진다. 입력으로 주어지는 모든 수는 정수이다.

www.acmicpc.net

첨에 내가 푼 접근법이 완전 틀려서 ㅠㅠ 결국 인터넷에 검색해서 다른분들 해설을 보고서야 해결했다.

 

DP문제 중 매우 유명한 배낭 문제로, 각각의 무게와 가치가 주어진 N개의 물건이 있을 때, 무게가 K가 넘지 않도록 물건들을 배낭에 넣어서 최대 가치를 구하는 문제이다.

 

접근법은 가치의 최대값을 저장하는 배열 dp[101][100001]을 선언한 뒤, 첫번째 물건부터 해당 물건을 넣었을 때와 넣지 않았을 때를 고려하여 무게별로 가치의 최대값을 구해주면 된다.

 

점화식은(i번째 물건에서 무게가 j일때를 구함)

dp[i][j] = dp[i-1][j] (W[i] > j 일 때)

               max(dp[i-1][j], dp[i-1][j - W[i]] + V[i]) (W[i] <= j 일 때)

 

위 식에서 dp[i-1][j]는 i번째 물건을 넣지 않은 경우, dp[i-1][j - W[i]] + V[i]는 i번째 물건을 넣은 경우가 된다. 둘 중 최대값으로 dp를 업데이트 하는 것

 

이렇게 되면

dp[1][K]에는 첫번째 물건만 고려했을 때의 최대 가치

dp[2][K]에는 첫번째물건 ~ 두번째 물건을 고려했을 때의 최대 가치

dp[3][K]에는 첫번째물건 ~ 세번째 물건을 고려했을 때의 최대 가치

.

.

dp[N][K]에는 첫번째물건 ~ N번째 물건을 고려했을 때의 최대 가치

가 담기게 된다.

 

구현이 익숙해질 때까지 연습하자

#include <iostream>
#include <algorithm>
using namespace std;

int dp[101][100001];

int main(void) {
	int N, K;
	int W[101], V[101];

	scanf("%d %d", &N, &K);
	for (int i = 1; i <= N; i++) scanf("%d %d", W + i, V + i);

	for (int i = 1; i <= N; i++) {
		for (int j = 1; j <= K; j++) {
			if (W[i] <= j) {
				dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - W[i]] + V[i]);
			}
			else {
				dp[i][j] = dp[i - 1][j];
			}
		}
	}

	printf("%d", dp[N][K]);
}

'Algorithm > 백준' 카테고리의 다른 글

[백준] 1021번: 회전하는 큐  (0) 2020.03.12
[백준] 16500번: 문자열 판별  (0) 2020.03.03
[백준] 11051번: 이항 계수 2  (0) 2020.03.02
[백준] 11570번: 오르막 수  (0) 2020.02.26
[백준] 11052번: 카드 구매하기  (0) 2020.02.17