01背包问题
给定物品的数量n(每一种物品只有一件)以及每件物品的价值,一个容量为v的背包,问怎样装物品使总价值最大。
朴素算法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 #include <iostream> #include <cstdio> #include <algorithm> using namespace std;const int N = 1010 ;int v[N], w[N]; int f[N][N];int n, m;int main () { scanf ("%d%d" , &n, &m); for (int i = 1 ; i <= n; i++) scanf ("%d%d" , &v[i], &w[i]); for (int i = 1 ; i <= n; i++) for (int j = 0 ; j <= m; j++) { f[i][j] = f[i - 1 ][j]; if (v[i] <= j) f[i][j] = max (f[i][j], f[i - 1 ][j - v[i]] + w[i]); } cout << f[n][m] << endl; return 0 ; }
优化
优化之前先看一下滚动数组 。使用滚动数组可以大大减少空间复杂度。
二维变一维,最终优化结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std;const int N = 1010 ;int v[N], w[N];int n, m, f[N];int main () { cin >> n >> m; for (int i = 1 ; 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]); cout << f[m] << endl; return 0 ; }
完全背包问题
给定n种物品(每一种物品有无限个)以及每一种物品的价值,一个容量为v的背包,问怎样装物品使价值最大。
朴素算法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std;const int N = 1010 ;int v[N], w[N];int n, m;int f[N][N];int main () { cin >> n >> m; for (int i = 1 ; i <= n; i++) cin >> v[i] >> w[i]; for (int i = 1 ; i <= n; i++) for (int j = 0 ; j <= m; j++) for (int k = 0 ; k * v[i] <= j; k++) f[i][j] = max (f[i][j], f[i - 1 ][j - k * v[i]] + k * w[i]); cout << f[n][m] << endl; return 0 ; }
优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std;const int N = 1010 ;int v[N], w[N];int n, m;int f[N][N];int main () { cin >> n >> m; for (int i = 1 ; i <= n; i++) cin >> v[i] >> w[i]; for (int i = 1 ; i <= n; i++) for (int j = 0 ; j <= m; j++) { f[i][j] = f[i - 1 ][j]; if (j >= v[i]) f[i][j] = max (f[i][j], f[i][j - v[i]] + w[i]); } cout << f[n][m] << endl; return 0 ; }
优化成一维
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std;const int N = 1010 ;int v[N], w[N];int n, m;int f[N];int main () { cin >> n >> m; for (int i = 1 ; i <= n; i++) cin >> v[i] >> w[i]; for (int i = 1 ; i <= n; i++) for (int j = v[i]; j <= m; j++) f[j] = max (f[j], f[j - v[i]] + w[i]); cout << f[m] << endl; return 0 ; }
多重背包问题
朴素算法