Book Shop
Explicación
Para cada libro , o lo compramos, gastando para ganar páginas, o lo saltamos y no ganamos nada. Este es el problema de la mochila 0/1, con costo , valor y capacidad , lo que permite una solución de DP.
Sea el número máximo de páginas obtenible usando solo los primeros libros con un presupuesto de a lo sumo . El caso base es para todo , ya que sin libros disponibles no se pueden obtener páginas, independientemente del presupuesto.
La transición queda así:
- por defecto (saltar el libro )
- si , en su lugar podemos comprar el libro , dando
La respuesta final es .
Mochila 1D
Como solo depende de la fila , no hace falta conservar todas las filas: podemos comprimir la DP en un solo arreglo 1D de tamaño , sobrescribiéndolo in situ a medida que avanzamos. Para cada libro , iteramos de hacia abajo hasta , actualizando . Ir hacia abajo importa: mantiene con el valor del libro anterior (fila ) cuando lo leemos, en vez de un valor ya actualizado para el libro (lo que nos permitiría comprar el mismo libro dos veces).
Implementación
Complejidad temporal:
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
int x;
cin >> n >> x;
vector<int> cost(n);
vector<int> pages(n);
for (int i = 0; i < n; i++) { cin >> cost[i]; }
for (int i = 0; i < n; i++) { cin >> pages[i]; }
/*
* dp[i][j] es el mayor número de páginas que se pueden comprar de
* los primeros i libros gastando a lo sumo j de dinero.
*/
vector<vector<int>> dp(n + 1, vector<int>(x + 1));
for (int i = 1; i <= n; i++) {
int curr_cost = cost[i - 1];
int curr_pages = pages[i - 1];
for (int j = 1; j <= x; j++) {
/*
* si no se compra el libro actual, el número de páginas es
* el mismo que el número de páginas compradas con los primeros i-1 libros
* usando j de dinero
*/
dp[i][j] = dp[i - 1][j];
if (curr_cost <= j) {
/*
* si se puede comprar el libro actual, entonces guardar el mayor
* número de páginas usando el dinero restante después de comprar
* el libro actual más las páginas del libro actual.
*/
dp[i][j] = max(dp[i][j], dp[i - 1][j - curr_cost] + curr_pages);
}
}
}
cout << dp[n][x] << '\n';
}import java.io.*;
import java.util.*;
public class bookShop {
public static void main(String[] args) throws IOException {
BufferedReader b = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(b.readLine());
int N = Integer.parseInt(st.nextToken());
int X = Integer.parseInt(st.nextToken());
// Leer el arreglo de costos.
int[] costs = new int[N];
st = new StringTokenizer(b.readLine());
for (int i = 0; i < N; i++) { costs[i] = Integer.parseInt(st.nextToken()); }
// Leer el arreglo de páginas.
int[] pages = new int[N];
st = new StringTokenizer(b.readLine());
for (int i = 0; i < N; i++) { pages[i] = Integer.parseInt(st.nextToken()); }
// dp[i][j] es cuántas páginas tienes de los primeros i libros,
// después de gastar j de dinero.
int[][] dp = new int[N + 5][X + 5];
for (int book = 0; book < N; book++) {
for (int money = 0; money <= X; money++) {
dp[book + 1][money] = dp[book][money];
int prev = money - costs[book];
if (prev >= 0) {
// El número total de páginas que tenemos si compramos este libro.
int newState = dp[book][prev] + pages[book];
dp[book + 1][money] = Integer.max(dp[book + 1][money], newState);
}
}
}
// Imprimir la respuesta.
System.out.println(dp[N][X]);
}
}