代码实现:
递归实现
#include<iostream> using namespace std; int a[30]; int N; int Ways(int w, int k) {//从前k种物品中选择一些,凑成体积w的做法物品 if (w == 0) return 1;//w=0,一个都不选,只有一种选法 if (k <= 0) return 0;//没有选择方法 return Ways(w, k - 1) + Ways(w - a[k], k - 1);//不选第k种物品的选法+选了第k种物品的选法 } int main() { cin >> N; for (int i = 1; i <= N; i++) cin >> a[i]; cout << Ways(40, N); return 0; }
动规解法:
#include<iostream> using namespace std; int a[30]; int N; int Ways[40][30];//Ways[i][j]表示从前j种物品里凑出体积i的方法数 int main() { cin >> N; memset(Ways, 0, sizeof(Ways)); for (int i = 1; i <= N; i++) { cin >> a[i]; Ways[0][i] = 1; } Ways[0][0] = 1; for (int w = 1; w <= 40; w++) { for (int k = 1; k <= N; k++) { if (w - a[k] >= 0) Ways[w][k] = Ways[w][k - 1] + Ways[w - a[k]][k - 1];//不取第k种物品的做法+取第k种物品的做法 else Ways[w][k] = Ways[w][k - 1];//无法取第k种物品 } } cout << Ways[40][N]; cin >> N; return 0; }
例 0-1背包问题
解题思路
要实现滚动数组的思想必须从右向左赋值,
代码实现:
#include<iostream> #include<algorithm> using namespace std; const int N=3500; const int M = 12880; int W[N], D[N], Rate[M]; int main() { int n, m; cin >> n>>m; memset(Rate, 0, sizeof(Rate)); for (int i = 0; i < n;i++) { cin >> W[i] >> D[i]; } for (int i = 0; i < n; i++) { for (int j = m; j >= W[i]; j--) { Rate[j] = max(Rate[j - W[i]] + D[i], Rate[j]); } } cout << Rate[m] << endl; cin >> n; return 0; }
下面是利用二维数组完成:
#include<iostream> #include<algorithm> using namespace std; const int N=3500; const int M = 12880; int W[N], D[N], Rate[N][M]; int main() { int n, m; cin >> n>>m; memset(Rate, 0, sizeof(Rate)); for (int i = 1; i <=n;i++) { cin >> W[i] >> D[i]; } for (int i = 1; i <= n; i++) { for (int j = 1; j < W[i]; j++) Rate[i][j] = Rate[i - 1][j]; for (int j = W[i]; j <= m;j++) { Rate[i][j] = max(Rate[i - 1][j - W[i]] + D[i], Rate[i - 1][j]);//后i种商品组成质量j的最大价值=max(有第i种商品参与的最大值,无第i种商品参与的最大值) } } cout << Rate[n][m] << endl; cin >> n; return 0; }