Aladdin's knapsack#1661

Aladdin's knapsack (Editorial)

Let dp_k[s] be the maximum value of cargo with a weight of at most , considering only the first types of items.

Now, consider two possible options when forming cargo of weight :

dp_k[i] = dp_{k - 1}[i]
dp_k[i] = dp_k[i - w_k] + v_k.

Since the goal is to maximize the cargo value, we obtain the following recurrence relation:

dp_k[i] = max(dp_{k - 1}[i], dp_k[i - w_k] + v_k), w_k \le i \le s

Base cases:

dp_0[i] = 0~и~dp_k[0] = 0

Let the function f(k, s) compute the maximum value of cargo that can be packed into a knapsack with a weight limit of , using the first types of items. Then, the next recurrence relation holds:

f(k, s) = max(f(k - 1, s), f(k, s - w[k]) + v[k])

Finally, we need to compute the value of f(k, s) using memoization.

Algorithm implementation

Declare the arrays:

#define MAXW 252
#define MAXN 37
int w[MAXN], p[MAXN];
int dp[MAXW];

Read the input data.

scanf("%d %d", &s, &n);
for (i = 0; i < n; i++)
  scanf("%d %d", &w[i], &p[i]);

Process types of items sequentially.

for (k = 0; k < n; k++)
{

Update the values in the array, considering the possibility of using items of type . Since the number of items of each type is unlimited, each item can be chosen multiple times.

  for (i = w[k]; i <= s; i++)
    dp[i] = max(dp[i], dp[i - w[k]] + p[k]);
}

Print the answer.

printf("%d\n", dp[s]);

Algorithm implementation — recursion

Declare the arrays:

#define MAXW 252
#define MAXN 37
#define INF 2000000000
int w[MAXN], v[MAXN];
int dp[MAXN][MAXW];

The function f(k, s) computes the maximum value of cargo that can be packed into a knapsack with a weight limit of , using the first types of items.

int f(int k, int s)
{

If k = 0 or s = 0, the knapsack is empty, and its value is .

  if (k == 0 || s == 0) return 0;

If s < 0, we have exceeded the allowed weight, making this option invalid. Therefore, we return  (where is a sufficiently large number).

  if (s < 0) return -INF;

If the value of f(k, s) is already computed, return it.

  if (dp[k][s] != -1) return dp[k][s];

Compute f(k, s) and store it in dp[k][s].

  return dp[k][s] = max(f(k - 1, s), f(k, s - w[k]) + v[k]);
}

The main part of the program. Read the input data.

scanf("%d %d", &s, &n);
for (i = 1; i <= n; i++)
  scanf("%d %d", &w[i], &v[i]);

Compute and print the answer.

memset(dp, -1, sizeof(dp));
printf("%d\n", f(n, s));