mirror of
https://github.com/Estom/notes.git
synced 2026-04-04 11:27:59 +08:00
123
This commit is contained in:
@@ -108,7 +108,7 @@ $$
|
||||
* 树形动态规划。非线性规模增长。非线性决策过程。第二个规模增长方向构成该阶段的状态集合(每个阶段的状态并非一个),但是每个阶段的状态数量不确定。例如:三角形数组最小路径和、单向最短路径问题。时间复杂度为O(n*m)//m表示某一阶段最大的状态数量。
|
||||
* 矩阵动态规划。非线性规模增长。非线性决策。第二个规模增长方向与第一个规模增长方向独立,不受第一个规模增长影响,每个阶段的状态数量是固定的。例如背包问题、n个骰子的点数问题。O(n*m)。由于矩阵可以用来表示图。也可以定义为图型动态规划
|
||||
* 序列动态规划。非线性规模增长。非线性决策。第二个规模增长的方向不受第一个规模增长的影响,矩阵动态规划的特殊形式,针对序列的动态规划。例如:最长公共子序列、正则表达式匹配。O(n*m)
|
||||
|
||||
* 二维规模增长的冬天规划,第一维表示的行,第二维表示列。第一维为主要的规模增长方向,第二维是第一维某一阶段的状态集合。
|
||||
## 4.1 线性动态规划
|
||||
|
||||
## 4.2 树型动态规划
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
> 矩阵可以看作是图的一种,怎么说?你可以把整个矩阵当成一个图,矩阵里面的每个位置上的元素当成是图上的节点,然后每个节点的邻居就是其相邻的上下左右的位置
|
||||
>
|
||||
> 矩阵类动态规划的两个规模增长方向可能存在两种情况:等价独立和非等价独立。例如不同路径和最大矩形中的规模增长方向,是等价独立的,两个规模增长的含义是一样的,比较好判断。但是在背包问题等其他子问题中。规模增长的方向是不等价,一个是背包容量的增长,另一个是物品数量的增长,通常比较难发现。
|
||||
>
|
||||
> 在矩阵动态规划中,两个维度的增长方向是可以相互交换的。只要设计好即可。但有可能存在一个简单一个复杂的情况。
|
||||
> * 不同路径
|
||||
> * 最大矩形
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
## 投资问题
|
||||
|
||||
|
||||
### 问题描述
|
||||
|
||||
m元钱,n个项目。f_i(x)表示x元钱投入项目i的效益。求最大效益。
|
||||
|
||||

|
||||
|
||||
|
||||
### 问题分析
|
||||
|
||||
|
||||
### 算法设计
|
||||
|
||||
* 问题分解划分阶段:规模增长的方向有两个。第一个是投资的金额想,第二个是项目选择k。x,k阶段。
|
||||
* 确定状态变量dp[x][k]表示投资x,第k个项目的最大收益。
|
||||
* 确定状态转移方程。
|
||||
|
||||
|
||||

|
||||
* 状态转移过程。
|
||||
|
||||

|
||||
### 算法效率
|
||||
|
||||
* O(n*m^2)
|
||||
|
||||
### 算法实现
|
||||
@@ -1,71 +0,0 @@
|
||||
# 背包问题
|
||||
## 1 01 背包问题
|
||||
|
||||
### 问题描述
|
||||
有m个物品,它们有各自的体积和价值,现有给定容量的背包c,如何让背包里装入的物品具有最大的价值总和?
|
||||
|
||||
### 问题分析
|
||||
|
||||
### 策略选择
|
||||
|
||||
|
||||
### 算法设计
|
||||
* 问题分解划分阶段:2个规模增长方向。背包的容量和物品。背包的容量表示为c=1,2,3,n。物品的重量表示为w1,w2,w3。物品的机制v1,v2,v3。第一个阶段表示是否添加物品。第二个阶段是背包容量的增长。
|
||||
* 确定状态dp[c,m]
|
||||
* 确定状态转移方程
|
||||
|
||||
$$
|
||||
dp[c,m]=max(dp[c-1],v[m]+dp[c-w[m]])
|
||||
$$
|
||||
|
||||
### 算法分析
|
||||
|
||||
### 算法实现
|
||||
|
||||
```
|
||||
for(int i=1;i<=n;i++)
|
||||
{
|
||||
for(int j=v;j>=weight[i];j--)
|
||||
{
|
||||
dp[j]=max(dp[j],dp[i-weight[i]]+value[i]);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 2 完全背包问题
|
||||
|
||||
### 问题描述
|
||||
|
||||
|
||||
### 问题分析
|
||||
|
||||
|
||||
### 策略选择
|
||||
|
||||
|
||||
### 算法设计
|
||||
|
||||
* 问题分解划分阶段:2个规模增长方向。背包的容量和物品。背包的容量表示为c=1,2,3,n。物品的重量表示为w1,w2,w3。物品的机制v1,v2,v3。第一个阶段表示是否添加物品。第二个阶段是背包容量的增长。
|
||||
* 确定状态dp[c,m]
|
||||
* 确定状态转移方程
|
||||
|
||||
$$
|
||||
dp[i][j]=max(dp[i][j],dp[i-1][j-k*weight[i]]+k*value[i]);
|
||||
$$
|
||||
* 确定边界
|
||||
### 算法分析
|
||||
|
||||
|
||||
### 算法实现
|
||||
```
|
||||
|
||||
for(i=1;i<=n;i++)
|
||||
{
|
||||
for(j=weight[i];j<=v;j++)
|
||||
{
|
||||
dp[j]=max(dp[j],dp[j-weight[i]]+value[i]);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 3 多重背包
|
||||
176
算法/A类:基本算法/5.9 背包问题.md
Normal file
176
算法/A类:基本算法/5.9 背包问题.md
Normal file
@@ -0,0 +1,176 @@
|
||||
# 背包问题
|
||||
## 1 01 背包问题
|
||||
|
||||
### 问题描述
|
||||
有N个物品,它们有各自的体积和价值,现有给定容量的背包c,如何让背包里装入的物品具有最大的价值总和?
|
||||
|
||||
N=4
|
||||
i 1,2,3,4
|
||||
w 2,3,4,5
|
||||
v 3,4,5,6
|
||||
c=8
|
||||
|
||||
### 问题分析
|
||||
|
||||
### 策略选择
|
||||
|
||||
|
||||
### 算法设计
|
||||
有两种动态规划的思路,本质上是一致的。背包的容量增长作为第一维,或者物品的数量增长作为第一维。
|
||||
|
||||
* 当背包的容量作为第一维的时候。背包容量为行,物品增长为列。
|
||||
* 问题分解划分阶段。背包容量容量为i,物品选择为j
|
||||
* 确定状态dp[i][j]表示背包容量为i的情况下,第j个物品放入或者不放入的最大价值。
|
||||
* 确定状态转移方程。分两种情况讨论。当背包容量为i时,第j个物品放入和第j个物品不放入。
|
||||
|
||||
$$
|
||||
dp[i][j]=max(dp[i][j-1],dp[i-w[i]][j-1])
|
||||
$$
|
||||
|
||||
|
||||
* 当物品的增长作为第一维的时候。物品增长为行,背包容量为列
|
||||

|
||||
* 问题分解划分阶段:2个规模增长方向。背包的容量和物品。物品选择i。背包的容量表示为j。第一个阶段表示是否添加物品。第二个阶段是背包容量的增长。
|
||||
* 确定状态dp[i][j]表示第i个物品,在背包容量j的情况下的最大价值。
|
||||
* 确定状态转移方程
|
||||
|
||||
$$
|
||||
dp[i][j]=max(dp[i-1][j],v[i]+dp[i-1][j-w[i]])
|
||||
$$
|
||||
|
||||
> 两种计算方式完全一致。
|
||||
|
||||
### 算法分析
|
||||
|
||||
### 算法实现
|
||||
```C++
|
||||
#include<iostream>
|
||||
using namespace std;
|
||||
#include <algorithm>
|
||||
|
||||
int main()
|
||||
{
|
||||
int w[5] = { 0 , 2 , 3 , 4 , 5 }; //商品的体积2、3、4、5
|
||||
int v[5] = { 0 , 3 , 4 , 5 , 6 }; //商品的价值3、4、5、6
|
||||
int bagV = 8; //背包大小
|
||||
int dp[5][9] = { { 0 } }; //动态规划表
|
||||
|
||||
for (int i = 1; i <= 4; i++) {
|
||||
for (int j = 1; j <= bagV; j++) {
|
||||
if (j < w[i])
|
||||
dp[i][j] = dp[i - 1][j];
|
||||
else
|
||||
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - w[i]] + v[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//动态规划表的输出
|
||||
for (int i = 0; i < 5; i++) {
|
||||
for (int j = 0; j < 9; j++) {
|
||||
cout << dp[i][j] << ' ';
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
最优的背包价值路径回溯方法
|
||||

|
||||
```C++
|
||||
#include<iostream>
|
||||
using namespace std;
|
||||
#include <algorithm>
|
||||
|
||||
int w[5] = { 0 , 2 , 3 , 4 , 5 }; //商品的体积2、3、4、5
|
||||
int v[5] = { 0 , 3 , 4 , 5 , 6 }; //商品的价值3、4、5、6
|
||||
int bagV = 8; //背包大小
|
||||
int dp[5][9] = { { 0 } }; //动态规划表
|
||||
int item[5]; //最优解情况
|
||||
|
||||
void findMax() { //动态规划
|
||||
for (int i = 1; i <= 4; i++) {
|
||||
for (int j = 1; j <= bagV; j++) {
|
||||
if (j < w[i])
|
||||
dp[i][j] = dp[i - 1][j];
|
||||
else
|
||||
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - w[i]] + v[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void findWhat(int i, int j) { //最优解情况
|
||||
if (i >= 0) {
|
||||
if (dp[i][j] == dp[i - 1][j]) {
|
||||
item[i] = 0;
|
||||
findWhat(i - 1, j);
|
||||
}
|
||||
else if (j - w[i] >= 0 && dp[i][j] == dp[i - 1][j - w[i]] + v[i]) {
|
||||
item[i] = 1;
|
||||
findWhat(i - 1, j - w[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void print() {
|
||||
for (int i = 0; i < 5; i++) { //动态规划表输出
|
||||
for (int j = 0; j < 9; j++) {
|
||||
cout << dp[i][j] << ' ';
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
cout << endl;
|
||||
|
||||
for (int i = 0; i < 5; i++) //最优解输出
|
||||
cout << item[i] << ' ';
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
findMax();
|
||||
findWhat(4, 8);
|
||||
print();
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## 2 完全背包问题
|
||||
|
||||
### 问题描述
|
||||
|
||||
完全背包(unbounded knapsack problem)与01背包不同就是每种物品可以有无限多个:一共有N种物品,每种物品有无限多个,第i(i从1开始)种物品的重量为w[i],价值为v[i]。在总重量不超过背包承载上限W的情况下,能够装入背包的最大价值是多少?
|
||||
|
||||
### 问题分析
|
||||
|
||||
|
||||
### 策略选择
|
||||
|
||||
|
||||
### 算法设计
|
||||
|
||||
* 问题分解划分阶段:2个规模增长方向。背包的容量和物品。背包的个数增长i=1,2,3,n。背包容量为j。第一个阶段表示是否添加物品。第二个阶段是背包容量的增长。
|
||||
* 确定状态dp[i,j]
|
||||
* 确定状态转移方程
|
||||
|
||||
$$
|
||||
dp[i][j] = max{(dp[i-1][j − k*w[i]] + k*v[i]) for every k}
|
||||
$$
|
||||
* 确定边界
|
||||
### 算法分析
|
||||
|
||||
|
||||
### 算法实现
|
||||
|
||||
|
||||
## 3 多重背包
|
||||
|
||||
|
||||
### 问题描述
|
||||
多重背包(bounded knapsack problem)与前面不同就是每种物品是有限个:一共有N种物品,第i(i从1开始)种物品的数量为n[i],重量为w[i],价值为v[i]。在总重量不超过背包承载上限W的情况下,能够装入背包的最大价值是多少?
|
||||
### 算法设计
|
||||
```
|
||||
dp[i][j] = max{(dp[i-1][j − k*w[i]] + k*v[i]) for every k}
|
||||
```
|
||||
BIN
算法/A类:基本算法/image/2021-04-01-14-37-22.png
Normal file
BIN
算法/A类:基本算法/image/2021-04-01-14-37-22.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 74 KiB |
BIN
算法/A类:基本算法/image/2021-04-01-14-43-16.png
Normal file
BIN
算法/A类:基本算法/image/2021-04-01-14-43-16.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 177 KiB |
BIN
算法/A类:基本算法/image/2021-04-01-15-01-49.png
Normal file
BIN
算法/A类:基本算法/image/2021-04-01-15-01-49.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
BIN
算法/A类:基本算法/image/2021-04-01-15-06-07.png
Normal file
BIN
算法/A类:基本算法/image/2021-04-01-15-06-07.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
BIN
算法/A类:基本算法/image/2021-04-01-15-06-19.png
Normal file
BIN
算法/A类:基本算法/image/2021-04-01-15-06-19.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
Reference in New Issue
Block a user