Programación dinámica: problema de mochila 0-1
Los pasos generales de la programación dinámica:
- Análisis de la estructura del problema
- Establecimiento de relaciones recursivas
- Cálculo ascendente
- Seguimiento de la mejor solución
Ejemplo 0-1 problema de mochila
(Fuente del tema: https://www.acwing.com/problem/content/description/2/)
Descripción del título
Hay N artículos y una mochila con una capacidad de V. Cada artículo solo se puede usar una vez.
El volumen de los artículos es i V i , es el valor de W i .
Averigüe qué artículos cargar en la mochila para que el volumen total de estos artículos no exceda la capacidad de la mochila y el valor total sea el mayor.
Salida del valor máximo.
Formato de entrada
Dos números enteros N y V en la primera línea, separados por espacios, indican respectivamente el número de artículos y el volumen de la mochila.
Luego hay N filas, cada fila dos números enteros V i , W i , separados por espacios, respectivamente, y el volumen del i-ésimo valor de los elementos.
Formato de
salida Muestra un número entero, que representa el valor máximo.
Rango de datos
0 <N, V≤1000
0 <vi, wi≤1000
Ejemplo de entrada
4 5
1 2
2 4
3 4
4 5
Salida de muestra
8
Análisis de problemas
En el caso de un cierto tamaño de la mochila, encuentre el valor más alto del valor total, cada artículo tiene solo dos casos de selección y ninguna selección, y compare el valor total de los dos casos.
f [i] [j] significa mirar solo los primeros i elementos. Si el volumen total es j, ¿cuál es el valor total máximo?
resultado = max {f [n] [0 ~ V]}
f [i] [j]:
1. No elija el i-ésimo elemento, f [i] [j] = f [i-1] [j];
2. Elija el i-ésimo elemento, f [i] [j] = f [i-1] [jv [i];
Elija el más grande y más en dos casos: f [i] [j] = max {1,2}
Inicialización: f [0] [0] = 0;
Codigo 1
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1010;
int n,m; //n表示物体个数,m表示背包容量
int f[N][N];
int v[N], w[N] //v[N], w[N] 分别表示每个物品的体积和价值
int main(){
cin >> n >> m;
for(int i=0; i<n; i++){
cin >> v[i] >> w[i];
}
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++){
f[i][j] = f[i-1][j];
if(j >= v[i])
f[i][j] = max(f[i][j], f[i-1][j-v[i]] + w[i]);
}
int res = 0;
for(int i=0; i<=m; i++)
res = max(res,f[n][i]);
cout << res << endl;
return 0;
}
En la matriz bidimensional f[N][N]
basada en la optimización de la matriz bidimensional f[N][N]
optimizada para f[N]
representar dicho volumen máximo de la mochila antes del i-ésimo valor de j y el número del artículo, una vez por cada bucle exterior, f [m] a actualizar;
Codigo 2
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1010;
int n,m; //n表示物体个数,m表示背包容量
int f[N]; //表示背包体积为j时前i个物品的最大价值为多少
int v[N], w[N] //v[N], w[N] 分别表示每个物品的体积和价值
int main(){
cin >> n >> m;
for(int i=0; i<n; i++){
cin >> v[i] >> w[i];
}
for(int i=1; i<=n; i++)
for(int j=m; j>=v[i]; j--){
f[j] = max(f[j], f[j-v[i]] + w[i]); //f[j]滚动记录最优解
}
cout << f[m] << endl;
return 0;
}