You are given a knapsack capacity W and n gold bars with weights w[0..n-1]. Each bar can be taken at most once (no repetitions, no fractional taking). Every bar’s value equals its weight. Select a subset of bars whose total weight does not exceed W and is as large as possible. Return that maximum achievable weight.
This is the 0-1 Knapsack Problem specialized to the case value[i] = weight[i]. In this special case, maximizing total value is equivalent to maximizing total weight—so it also aligns with the optimization version of the classic Subset Sum Problem (find the largest sum ≤ W).
import java.util.*;
classGoldRec {
intdfs(int[] w, int i, int cap) {
if (i == w.length|| cap == 0) return 0;
int skip = dfs(w, i+1, cap);
if (w[i]> cap) return skip;
int take = w[i]+ dfs(w, i+1, cap - w[i]);
return Math.max(skip, take);
}
inttakeMaxGold(int[] w, int W) { return dfs(w, 0, W); }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
from typing import List
def_gold_rec(w: List[int], i: int, cap: int) -> int:
if i == len(w) or cap ==0:
return0 skip = _gold_rec(w, i+1, cap)
if w[i] > cap:
return skip
take = w[i] + _gold_rec(w, i+1, cap - w[i])
return max(skip, take)
deftake_max_gold_rec(w: List[int], W: int) -> int:
return _gold_rec(w, 0, W)
classGoldMemo {
int[][] memo;
intdfs(int[] w, int i, int cap) {
if (i == w.length|| cap == 0) return 0;
if (memo[i][cap]!=-1) return memo[i][cap];
int skip = dfs(w, i+1, cap);
if (w[i]> cap) return memo[i][cap]= skip;
int take = w[i]+ dfs(w, i+1, cap - w[i]);
return memo[i][cap]= Math.max(skip, take);
}
inttakeMaxGold(int[] w, int W) {
memo =newint[w.length][W+1];
for (int i = 0; i < w.length; i++) java.util.Arrays.fill(memo[i], -1);
return dfs(w, 0, W);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
from functools import lru_cache
from typing import List
deftake_max_gold_memo(w: List[int], W: int) -> int:
@lru_cache(None)
deff(i: int, cap: int) -> int:
if i == len(w) or cap ==0:
return0 skip = f(i+1, cap)
if w[i] > cap:
return skip
take = w[i] + f(i+1, cap - w[i])
return max(skip, take)
return f(0, W)
dp[i][c] = best weight using first i items with capacity c.
Transition: if w[i-1] ≤ c, dp[i][c] = max(dp[i-1][c], w[i-1] + dp[i-1][c - w[i-1]]) else copy dp[i-1][c].
#include<vector>longlongtakeMaxGoldBU2D(const std::vector<int>& w, int W){
int n = (int)w.size();
std::vector<std::vector<longlong>> dp(n+1, std::vector<longlong>(W+1, 0));
for (int i =1; i <= n; ++i){
for (int c =0; c <= W; ++c){
dp[i][c] = dp[i-1][c];
if (w[i-1] <= c){
dp[i][c] = std::max(dp[i][c], (longlong)w[i-1] + dp[i-1][c - w[i-1]]);
}
}
}
return dp[n][W];
}
classGoldBU2D {
inttakeMaxGold(int[] w, int W) {
int n = w.length;
int[][] dp =newint[n+1][W+1];
for (int i = 1; i <= n; i++) {
for (int c = 0; c <= W; c++) {
dp[i][c]= dp[i-1][c];
if (w[i-1]<= c) {
dp[i][c]= Math.max(dp[i][c], w[i-1]+ dp[i-1][c - w[i-1]]);
}
}
}
return dp[n][W];
}
}
1
2
3
4
5
6
7
8
9
10
11
12
deftake_max_gold_bu_2d(w, W):
n = len(w)
dp = [[0]*(W+1) for _ in range(n+1)]
for i in range(1, n+1):
wi = w[i-1]
for c in range(W+1):
dp[i][c] = dp[i-1][c]
if wi <= c:
cand = wi + dp[i-1][c-wi]
if cand > dp[i][c]:
dp[i][c] = cand
return dp[n][W]
If you need to reconstruct which bars are chosen, store predecessor info (e.g., keep a separate take[i][c] boolean in the 2D version, then backtrack). For the 1D optimized version, reconstruct by re-running with reverse reasoning or keeping additional tracking.
Because value equals weight, returns are always ≤ W and monotonic in W.
This file links to the general 0-1 Knapsack Problem for the broader formulation with independent value array.