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
지금까지 풀었던 동적 계획법 메모이제이션 문제들과 비슷한 거 같은데 표를 만들어서 푸는 냅색문제라 신기했다.
첫 접근 방식
회의실 배정 문제처럼 무게, 가중치를 작은 순서대로 정렬 후 가방에 들어갈 수 있다면 추가 해주는 식으로 풀었다가 틀렸다.
- 중간에서부터 골랐을 때가 처음 부터 골랐을 때보다 가중치가 더 높은 경우가 있어 실패.
문제 풀이
행의 개수는 물건의 개수, 열의 개수는 가방의 무게 1~입력받은 수 까지 설정하고 풀었다. (이전 것과 더해주어야 하니 둘다 0이 아닌 1에서 부터 시작하여 인덱스가 입력받은거 보다 1씩 큼)
- ex)이전 물건의 무게가 2, 가중치가 3, 현재 물건의 무게가 5, 가중치가 10
물건 \ 무게 | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
2, 3 | 0 | 0 | 3 | 3 | 6 | 6 | 9 |
5, 10 | 0 | 0 | 3 | 3 | 6 | 10 | 10 |
현재 무게가 5 이상일 때 부터 무게가 들어가니, 전 물건의 5일 때의 가중치, 전 물건의 무게 0의 가중치에 현재 물건의 가중치를 더한 값을 비교하여 큰값을 표에 넣는다.
- 연두색 + 현재 물건 가중치, 남색 비교 -> 6보다는 0+10이 더크니 주황색은 10.
이런 작업을 반복하다 보면 표의 가장 오른쪽 하단은 가중치가 가장 크게 들어가므로 그 값이 답이된다.
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
namespace Baekjoon.Gold
{
class _12865
{
static void Main(string[] args)
{
int[] n = Array.ConvertAll(Console.ReadLine().Split(), int.Parse);
int[][] things = new int[n[0]][];
for(int i = 0; i<n[0]; i++)
things[i] = Array.ConvertAll(Console.ReadLine().Split(), int.Parse);
//0으로 초기화 - 행: 물건의 개수, 열: 배낭의 무게
int[][] backpack = new int[n[0]+1][];
for (int i = 0; i <=n[0]; i++)
backpack[i] = Enumerable.Repeat(0, n[1]+1).ToArray();
for (int i = 1; i<=n[0]; i++)
{
for(int j = 1; j<=n[1]; j++)
{
//물건의 무게가 배낭에 들어가면
if (things[i - 1][0] <= j)
//현 무게에 해당하는 전물건의 가치, 무게가(현가방무게 - 현물건무게)인 가치 + 현물건의 가치 비교
backpack[i][j] = Math.Max(backpack[i - 1][j], backpack[i - 1][j - things[i - 1][0]] + things[i - 1][1]);
//안들어가면 그냥 전물건의 가치 적용
else
backpack[i][j] = backpack[i - 1][j];
}
}
Console.WriteLine(backpack[n[0]][n[1]]);
}
}
}
'문제 풀이 > C#' 카테고리의 다른 글
[7569] - 토마토 (0) | 2022.10.01 |
---|---|
[7576] - 토마토 (0) | 2022.10.01 |
[17404] - RGB거리 2 (0) | 2022.09.29 |
[9663] - N-Queen (0) | 2022.09.28 |
[2606] - 바이러스 (0) | 2022.09.27 |