|
|
|
@ -223,3 +223,55 @@ int main() {
|
|
|
|
|
|
|
|
|
|
### 五、完全背包之恰好装满
|
|
|
|
|
**[$AcWing$ $1023$. 买书](https://www.acwing.com/problem/content/1025/)**
|
|
|
|
|
|
|
|
|
|
**二维数组**
|
|
|
|
|
```cpp {.line-numbers}
|
|
|
|
|
#include <bits/stdc++.h>
|
|
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
const int N = 1010;
|
|
|
|
|
int v[5] = {0, 10, 20, 50, 100};
|
|
|
|
|
int f[5][N];
|
|
|
|
|
|
|
|
|
|
int main() {
|
|
|
|
|
int m;
|
|
|
|
|
cin >> m;
|
|
|
|
|
// 前0种物品,体积是0的情况下只有一种方案
|
|
|
|
|
f[0][0] = 1;
|
|
|
|
|
for (int i = 1; i <= 4; i++)
|
|
|
|
|
for (int j = 0; j <= m; j++) {
|
|
|
|
|
f[i][j] = f[i - 1][j];
|
|
|
|
|
if (v[i] <= j) f[i][j] += f[i][j - v[i]];
|
|
|
|
|
}
|
|
|
|
|
printf("%d\n", f[4][m]);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
**一维数组**
|
|
|
|
|
```cpp {.line-numbers}
|
|
|
|
|
#include <bits/stdc++.h>
|
|
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
const int N = 1010;
|
|
|
|
|
int v[5] = {0, 10, 20, 50, 100};
|
|
|
|
|
int f[N];
|
|
|
|
|
|
|
|
|
|
// 体积限制是恰好是,因此需要初始化f[0][0]为合法解1,其他位置为非法解0。
|
|
|
|
|
int main() {
|
|
|
|
|
int m;
|
|
|
|
|
cin >> m;
|
|
|
|
|
// 前0种物品,体积是0的情况下只有一种方案
|
|
|
|
|
f[0] = 1;
|
|
|
|
|
for (int i = 1; i <= 4; i++)
|
|
|
|
|
for (int j = v[i]; j <= m; j++)
|
|
|
|
|
f[j] += f[j - v[i]];
|
|
|
|
|
// 输出
|
|
|
|
|
printf("%d\n", f[m]);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
**总结**
|
|
|
|
|
① 完全背包的经典优化是哪个混蛋想出来的,真它娘的是个人才。
|
|
|
|
|
② 对比$01$背包与完全背包的代码,发现就是一正一反。
|
|
|
|
|
③ 完全背包求最大值与恰好装满的方案数,除了初始化不同,其它的一样。$f[i][0]=1$这样的初始化,我也服了~
|
|
|
|
|
④ 背包问题这样的经典代码,除了理解算法原理,会推导外,重点还是模板背诵。用模板知识解决实际问题才是考试的本质,虽然考试不一定能选拔出能力强的人才,但能选拔出做过这方面训练的人员。
|
|
|
|
|