From c85bea0aaf3fb7c9b26dfec182e59ce790947854 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=BB=84=E6=B5=B7?= <10402852@qq.com>
Date: Wed, 13 Mar 2024 16:45:08 +0800
Subject: [PATCH] 'commit'
---
TangDou/AcWing/BeiBao/1013.md | 41 +++++++-------
TangDou/AcWing/BeiBao/9.md | 8 ++-
TangDou/AcWing/BeiBao/背包问题专题.md | 62 +++++++++++++++++++++
3 files changed, 86 insertions(+), 25 deletions(-)
diff --git a/TangDou/AcWing/BeiBao/1013.md b/TangDou/AcWing/BeiBao/1013.md
index b8fe2fb..b59f7cd 100644
--- a/TangDou/AcWing/BeiBao/1013.md
+++ b/TangDou/AcWing/BeiBao/1013.md
@@ -77,8 +77,26 @@ $3$个公司,$3$台机器,**机器都是一样的,一样的,记住,一
**答**:$1$号公司得到$1$台机器,$2$号公司得到$1$台机器,$3$号公司得到$1$台机器,就是$30+20+20=70$,此时国家利益最大。
+### 二、分组背包
+转换成 **分组背包问题** ,做 **等价变换**
+
+
+① 第$i$个公司就是第$i$个分组
+② 每个分组中可以一台也不要,可以要一台,可以要两台,...,可以要$S_i$台
+
+
+**分组背包** 的 **闫氏DP分析法**
+
+
+
+初始状态 :$f[0][0]$
+
+目标状态 :$f[N][M]$
+
+
### 三、不同$OJ$此题的差别
两者差别:
+
* $AcWing$:答案不唯一,输出任意合法方案即可($Special$ $Judge$)
* 洛谷: $P.S.$要求答案的字典序最小
@@ -123,27 +141,6 @@ for (int k = 1; k <= j; k++) {
$k$的含义是当前分组中的物品个数,是由小到大的。而这里的计算式是$j-k$,这个东西在$k$前面的符号是负数,也就是$k$越小,值越大,$k$越大,值越小。按个循环逻辑,随着$k$的长大,就会枚举到更小的$j-k$,也就是枚举到更小的字典序。如果没有等号,就是$k$越来越大时,$j-k$越来越小,当价值一样时,越来越小的个数无法更新结果,反之,如果有等号,就是获取到字典序。
-### 四、分组背包
-转换成 **背包$DP$** 问题,需要对里面的一些叙述做出 **等价变换**
-
-① 对于分给第$i$个公司的不同机器数量可以分别看作是一个物品组内的物品数量。
-
-② 物品$k$的含义:分给第$i$个公司$k$台机器
-
-③ 物品$k$的体积:因为一个机器算一个,所以体积也是$k$
-
-④ 物品$k$的价值:$w_{k}$
-
-
-
-直接上 **分组背包** 的 **闫氏DP分析法**
-
-
-
-初始状态 :$f[0][0]$
-
-目标状态 :$f[N][M]$
-
**二维数组写法**
```cpp {.line-numbers}
@@ -297,7 +294,7 @@ int main() {
```
### 四、深度优先搜索
-数据范围比较小,$1<=N<=10,1<=M<=15$,把$m$个机器分配给$n$个公司,暴力遍历所有方案
+数据范围比较小,$1 \leq N \leq 10,1 \leq M \leq 15$,把$m$个机器分配给$n$个公司,暴力遍历所有方案
记录分配方案,如果能更新最优解,顺便更新一下最优解的分配方案
diff --git a/TangDou/AcWing/BeiBao/9.md b/TangDou/AcWing/BeiBao/9.md
index 5c8f049..e4b994d 100644
--- a/TangDou/AcWing/BeiBao/9.md
+++ b/TangDou/AcWing/BeiBao/9.md
@@ -90,9 +90,10 @@ int main() {
cin >> v[i][j] >> w[i][j]; // 第i个分组中物品的体积和价值
}
- for (int i = 1; i <= n; i++)
- for (int j = 0; j <= m; j++) {
- for (int k = 0; k <= s[i]; k++)
+ for (int i = 1; i <= n; i++) // 每组
+ for (int j = 0; j <= m; j++) { // 每个合法体积
+ f[i][j] = f[i - 1][j]; // 如果一个都不要,那么这一组就相当于白费,给你机会也不中用,继承于i-1
+ for (int k = 1; k <= s[i]; k++) // 选择第k个
if (j >= v[i][k])
f[i][j] = max(f[i][j], f[i - 1][j - v[i][k]] + w[i][k]); // 枚举每一个PK一下大小
}
@@ -100,6 +101,7 @@ int main() {
printf("%d", f[n][m]);
return 0;
}
+
```
### 四、一维数组版本
diff --git a/TangDou/AcWing/BeiBao/背包问题专题.md b/TangDou/AcWing/BeiBao/背包问题专题.md
index e19a6a2..9b32bbe 100644
--- a/TangDou/AcWing/BeiBao/背包问题专题.md
+++ b/TangDou/AcWing/BeiBao/背包问题专题.md
@@ -623,6 +623,68 @@ int main() {
### 八、分组背包
**[$AcWing$ $9$. 分组背包问题](https://www.acwing.com/problem/content/description/9/)**
+**二维状态**
+```cpp {.line-numbers}
+#include
+
+using namespace std;
+
+const int N = 110;
+int n, m;
+int f[N][N], v[N][N], w[N][N], s[N];
+
+int main() {
+ cin >> n >> m;
+ for (int i = 1; i <= n; i++) {
+ cin >> s[i]; // 第i个分组中物品个数
+ for (int j = 1; j <= s[i]; j++)
+ cin >> v[i][j] >> w[i][j]; // 第i个分组中物品的体积和价值
+ }
+
+ for (int i = 1; i <= n; i++) // 每组
+ for (int j = 0; j <= m; j++) { // 每个合法体积
+ f[i][j] = f[i - 1][j]; // 如果一个都不要,那么这一组就相当于白费,给你机会也不中用,继承于i-1
+ for (int k = 1; k <= s[i]; k++) // 选择第k个
+ if (j >= v[i][k])
+ f[i][j] = max(f[i][j], f[i - 1][j - v[i][k]] + w[i][k]); // 枚举每一个PK一下大小
+ }
+ // 输出打表结果
+ printf("%d", f[n][m]);
+ return 0;
+}
+
+```
+
+**一维状态**
+```cpp {.line-numbers}
+#include
+
+using namespace std;
+const int N = 110;
+
+int n, m;
+int v[N][N], w[N][N], s[N];
+int f[N];
+
+int main() {
+ cin >> n >> m;
+
+ for (int i = 1; i <= n; i++) {
+ cin >> s[i];
+ for (int j = 1; j <= s[i]; j++)
+ cin >> v[i][j] >> w[i][j];
+ }
+
+ for (int i = 1; i <= n; i++)
+ for (int j = m; j >= 0; j--)
+ for (int k = 1; k <= s[i]; k++)
+ if (j >= v[i][k])
+ f[j] = max(f[j], f[j - v[i][k]] + w[i][k]);
+
+ printf("%d\n", f[m]);
+ return 0;
+}
+```
**[$AcWing$ $1013$. 机器分配](https://www.acwing.com/problem/content/1015/)**
分组背包求最优路径
\ No newline at end of file