Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
hitoriray committed Apr 9, 2024
1 parent 90e6113 commit ea83c05
Show file tree
Hide file tree
Showing 53 changed files with 783 additions and 62 deletions.
8 changes: 4 additions & 4 deletions 算法基础/18线性DP+区间DP.md
Original file line number Diff line number Diff line change
Expand Up @@ -378,19 +378,19 @@ AGTAAGTAGGC

- 思路

1. 状态表示f[i,j]
1. 状态表示`f[i,j]`
1. 集合:**所有将a[1\~i]变成b[1\~j]的操作方式**
2. 属性:Min
2. 属性:**Min**

2. 状态计算 —— 集合划分

以最后一步的操作进行分类:

①删:如果把a[i]删掉之后a[1\~i]和b[1\~j]相同,此时状态转移为 $f[i-1, j] + 1$
①删:如果把`a[i]`删掉之后`a[1~i]``b[1~j]`相同,此时状态转移为 $f[i-1, j] + 1$

②增:在a[i]后面添加一个字符`b[j]`后的新字符串a与b相同,此时状态转移方程为 $f[i,j-1]+1$

③改:如果$a[i]\ne b[j]$才需要修改,把a[i]改为b[j]使得改完后的字符串a和b相同,此时状态转移方程为 $f[i-1,j-1]+1$
③改:如果$a[i]\ne b[j]$才需要修改,`a[i]`改为`b[j]`使得改完后的字符串`a``b`相同,此时状态转移方程为 $f[i-1,j-1]+1$

所以,最终的状态转移方程为:$f[i,j]=min(\{f[i-1,j],f[i,j-1],f[i-1,j-1]\}) + 1$

Expand Down
2 changes: 1 addition & 1 deletion 算法基础/1快排+归并+二分.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ void quick_sort(int q[], int l, int r)
do i ++ ; while (q[i] < x);
do j -- ; while (q[j] > x);
if (i < j) swap(q[i], q[j]);
}
}
// 3. 递归处理左右两部分
quick_sort(q, l, j);
quick_sort(q, j + 1, r);
Expand Down
2 changes: 1 addition & 1 deletion 算法提高/1. 动态规划/1.1 数字三角形模型.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

- 思路

![image-20231121211102033](E:\Typora\数据结构\算法提高\image\image-20231121211102033.png)
<img src="E:\Typora\数据结构\算法提高\1. 动态规划\image\1.1 数字三角形模型\image-20231121211102033.png" alt="image-20231121211102033" style="zoom:80%;" />

- [代码](E:\codes\C++\AcwingTest\方格取数.cpp)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,17 @@ int main()

## 扩展题

<img src="E:\Typora\数据结构\算法提高\image\image-20231122143416536.png" />
<img src="E:\Typora\数据结构\算法提高\1. 动态规划\image\1.2 最长上升子序列模型(LIS)\image-20231122143416536.png" style="zoom:80%;" />

<img src="E:\Typora\数据结构\算法提高\image\image-20231122143528185.png" alt="image-20231122143528185" style="zoom:80%;" />


<img src="E:\Typora\数据结构\算法提高\1. 动态规划\image\1.2 最长上升子序列模型(LIS)\image-20231122143528185.png" alt="image-20231122143528185" style="zoom:80%;" />

#### 1. [怪盗基德的滑翔翼](http://ybt.ssoier.cn:8088/problem_show.php?pid=1286)

- 思路:正向求一次LIS,再反向求一次LIS,res取每次f[i]的最大值。

<img src="E:\Typora\数据结构\算法提高\image\image-20231122154225608.png" alt="image-20231122154225608" style="zoom:80%;" />
<img src="E:\Typora\数据结构\算法提高\1. 动态规划\image\1.2 最长上升子序列模型(LIS)\image-20231122154225608.png" alt="image-20231122154225608" style="zoom:80%;" />

- [代码](E:/codes/C++/AcwingTest/怪盗基德的滑翔翼.cpp)

Expand All @@ -56,7 +58,7 @@ int main()

- 思路

<img src="E:\Typora\数据结构\算法提高\image\image-20231123094529218.png" />
<img src="E:\Typora\数据结构\算法提高\1. 动态规划\image\1.2 最长上升子序列模型(LIS)\image-20231123094529218.png" style="zoom:80%;" />

- [代码](E:/codes/C++/AcwingTest/登山.cpp)

Expand All @@ -69,22 +71,22 @@ int main()
#### 4. [友好城市](http://ybt.ssoier.cn:8088/problem_show.php?pid=1263)

- 思路
![友好城市思路图](image\image.png)
<img src="E:\Typora\数据结构\算法提高\1. 动态规划\image\1.2 最长上升子序列模型(LIS)\image.png" alt="友好城市思路图" style="zoom:80%;" />

- [代码](E:/codes/C++/AcwingTest/友好城市.cpp)

#### 5. [最大上升子序列和](http://ybt.ssoier.cn:8088/problem_show.php?pid=1285)

- 思路
![最大上升子序列和思路](image\image2.png)
<img src="E:\Typora\数据结构\算法提高\1. 动态规划\image\1.2 最长上升子序列模型(LIS)\image2.png" alt="最大上升子序列和思路" style="zoom:80%;" />
- [代码](E:/codes/C++/AcwingTest/最大上升子序列和.cpp)

#### 6. [拦截导弹](http://ybt.ssoier.cn:8088/problem_show.php?pid=1260)

- 思路
![拦截导弹思路](image\image3.png)
<img src="E:\Typora\数据结构\算法提高\1. 动态规划\image\1.2 最长上升子序列模型(LIS)\image3.png" alt="拦截导弹思路" style="zoom:80%;" />

<img src="image\image4.png" style="zoom:50%;" />
<img src="E:\Typora\数据结构\算法提高\1. 动态规划\image\1.2 最长上升子序列模型(LIS)\image4.png" style="zoom:50%;" />

将这道题与 [最长上升子序列II](../算法基础/18线性DP+区间DP.md) 的解法进行对比,我们可以惊奇地发现这道题的第二问其实就是求序列中的最长上升子序列。

Expand All @@ -104,7 +106,7 @@ int main()
#### 8. [最长公共上升子序列](https://www.acwing.com/problem/content/274/)

- [思路](https://www.acwing.com/solution/content/4955/):LIS和LCS的结合版
![Alt text](image\image5.png)
<img src="E:\Typora\数据结构\算法提高\1. 动态规划\image\1.2 最长上升子序列模型(LIS)\image5.png" alt="Alt text" style="zoom:80%;" />
> 注意:这里的划分是不重不漏的,而在LCS的划分是不漏但有重复的。
- [代码](E:/codes/C++/AcwingTest/最长公共上升子序列.cpp)
18 changes: 9 additions & 9 deletions 算法提高/1. 动态规划/1.3 背包问题.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
# 背包问题

- 题谱
![Alt text](image\image6.png)
<img src="E:\Typora\数据结构\算法提高\1. 动态规划\image\1.3 背包问题\image6.png" alt="Alt text" style="zoom:80%;" />

****

## 模板题

### 01背包

![Alt text](image\image1.3-1.png)
<img src="E:\Typora\数据结构\算法提高\1. 动态规划\image\1.3 背包问题\image1.3-1.png" alt="Alt text" style="zoom:80%;" />

### 完全背包

Expand All @@ -32,10 +32,10 @@
- [朴素版思路](../算法基础/17背包问题DP.md)

- 思路与完全背包问题一模一样。
![Alt text](image\image1.3-3.png)
<img src="E:\Typora\数据结构\算法提高\1. 动态规划\image\1.3 背包问题\image1.3-3.png" alt="Alt text" style="zoom:80%;" />

- [单调队列优化思路](https://www.acwing.com/solution/content/53507/)
![Alt text](image\image1.3-4.png)
<img src="E:\Typora\数据结构\算法提高\1. 动态规划\image\1.3 背包问题\image1.3-4.png" alt="Alt text" style="zoom:80%;" />

$f(i,j)$求的是$j$前面连续$s$个数的最大值
所以要维护一个长度为$s$的滑动窗口,取每个窗口的最大值。(要记得加一个偏移量$w$)
Expand Down Expand Up @@ -70,7 +70,7 @@ $f(i,j)$求的是$j$前面连续$s$个数的最大值
1. 与01背包结合

- 思路
![Alt text](image\image1.3-5.png)
<img src="E:\Typora\数据结构\算法提高\1. 动态规划\image\1.3 背包问题\image1.3-5.png" alt="Alt text" style="zoom:80%;" />
- [代码](E:/codes/C++/AcwingTest/二维费用的01背包问题.cpp)

****
Expand Down Expand Up @@ -138,7 +138,7 @@ int main()



![Alt text](image\image1.3-8.png) 总结:当我们把状态设置成`至少是`的时候,即使$j-v$是负数,也要从它转移过来,因为`至少是0`包括`至少是j-v(j-v为负数)`
<img src="E:\Typora\数据结构\算法提高\1. 动态规划\image\1.3 背包问题\image1.3-8.png" alt="Alt text" style="zoom:80%;" /> 总结:当我们把状态设置成`至少是`的时候,即使$j-v$是负数,也要从它转移过来,因为`至少是0`包括`至少是j-v(j-v为负数)`

> 1.体积不超过j:f全部为0,v >= 0
> 2.体积恰好是j:f[0] = 0, f[i] = ∞, v >= 0
Expand Down Expand Up @@ -217,7 +217,7 @@ int main()
#### 1. [数字组合](https://www.acwing.com/problem/content/280/)(01背包问题的方案数)

- 思路
![Alt text](image\image1.3-6.png)
<img src="E:\Typora\数据结构\算法提高\1. 动态规划\image\1.3 背包问题\image1.3-6.png" alt="Alt text" style="zoom:80%;" />

- [代码](E:/codes/C++/AcwingTest/数字组合.cpp)

Expand All @@ -232,7 +232,7 @@ int main()
#### 3. [买书](http://ybt.ssoier.cn:8088/problem_show.php?pid=1293)(完全背包问题的方案数)

- 思路
![Alt text](image\image1.3-7.png)
<img src="E:\Typora\数据结构\算法提高\1. 动态规划\image\1.3 背包问题\image1.3-7.png" alt="Alt text" style="zoom:80%;" />

- [代码](E:/codes/C++/AcwingTest/买书.cpp)

Expand Down Expand Up @@ -280,7 +280,7 @@ int main()
#### 1. [背包问题求具体方案](https://www.acwing.com/problem/content/12/)
- [思路](https://www.acwing.com/solution/content/2687/)
![Alt text](image\image1.3-9.png)
<img src="E:\Typora\数据结构\算法提高\1. 动态规划\image\1.3 背包问题\image1.3-9.png" alt="Alt text" style="zoom:80%;" />
- [代码](E:/codes/C++/AcwingTest/背包问题求具体方案.cpp)
路径追踪的`递归`写法可以参考这篇博客:[AcWing 1013. 机器分配【分组背包+背包DP输出方案—拓扑图分析】](https://www.acwing.com/solution/content/53963/)
Expand Down
4 changes: 2 additions & 2 deletions 算法提高/1. 动态规划/1.7 树形DP.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#### 1. [树的最长路径](https://www.lintcode.com/problem/1469/)

![image-20231206161445062](image/1.7 树形DP/image-20231206161445062.png)
<img src="image/1.7 树形DP/image-20231206161445062.png" alt="image-20231206161445062" style="zoom:100%;" />

- 思路

Expand Down Expand Up @@ -39,7 +39,7 @@

#### 2. [树的中心]()

![image-20231206173549805](image/1.7 树形DP/image-20231206173549805.png)
<img src="image/1.7 树形DP/image-20231206173549805.png"/>

- 思路

Expand Down
14 changes: 7 additions & 7 deletions 算法提高/1. 动态规划/1.8 数位DP.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#### 1. [度的数量]()

![image-20231207172209983](image/1.8 数位DP/image-20231207172209983.png)
<img src="image/1.8 数位DP/image-20231207172209983.png"/>

- 思路

Expand Down Expand Up @@ -79,7 +79,7 @@
>
> 所有集合的最高位已经固定(为j),后面的i-1位是不固定的,集合划分的依据是后面那一位的填法,可以填j, j+1, j+2, ..., 9中的一个,根据后面那一位(即第二位)的填法可以划分成若干类,假设第二位填的是k,因为最高位固定为j,那么可以去掉最高位,就变成了以最高位为k,且一共有i-1位的不降数的集合。所以,$f[i, j] = \sum_{j}^{9}f[i - 1, k])$。
![image-20231207231943222](image/1.8 数位DP/image-20231207231943222.png)
<img src="image/1.8 数位DP/image-20231207231943222.png"/>

与上一题的不同之处:求左侧集合的方案数使用的是递推,而不是上一题中的求组合数。

Expand All @@ -95,7 +95,7 @@
其他的思路与上一题类似。注意最高位不能填0!

![image-20231208102715230](image/1.8 数位DP/image-20231208102715230.png)
<img src="image/1.8 数位DP/image-20231208102715230.png" alt="image-20231208102715230" style="zoom:80%;" />

状态表示与上一题相同。状态计算变成了:$f[i, j]=\sum_{k=0}^9f[i-1,k](其中|j -k|\ge2)$

Expand All @@ -113,7 +113,7 @@
>
> 状态计算:$f[i,j,k]+=f[i-1,x,(k-j)\mod N](其中x为第i-1位填的数字)$
![image-20231208112153433](image/1.8 数位DP/image-20231208112153433.png)
<img src="image/1.8 数位DP/image-20231208112153433.png" alt="image-20231208112153433" style="zoom:80%;" />

- [代码](E:/codes/C++/AcwingTest/数字游戏II.cpp)

Expand All @@ -131,7 +131,7 @@
>
> f[i, j] += f[i - 1, k]。需要满足:① $j, k \ne 4$ ②$jk\ne 62$
![image-20231209113749253](image/1.8 数位DP/image-20231209113749253.png)
<img src="image/1.8 数位DP/image-20231209113749253.png" alt="image-20231209113749253" style="zoom:80%;" />

- [代码](E:/codes/C++/AcwingTest/不要62.cpp)

Expand All @@ -153,13 +153,13 @@

> f[i, j, a, b]表示总共有i位,最高位是j,且这个数模7的余数是a,各位数之和模7的余数是b的所有数的平方和。
![image-20231209171028204](image/1.8 数位DP/image-20231209171028204.png)
<img src="image/1.8 数位DP/image-20231209171028204.png" alt="image-20231209171028204" style="zoom:80%;" />

> 状态计算:$f[i, j, a, b] += f[i - 1, k, a - j \times 10^{i-1}, b - j]$
要想推出平方和,就必须记录当前的最高位j当前所在位数以及j后面的那一串数字的和以及它们的平方。

![image-20231209171818698](image/1.8 数位DP/image-20231209171818698.png)
<img src="image/1.8 数位DP/image-20231209171818698.png" alt="image-20231209171818698" style="zoom:80%;" />

详细思路参考:https://www.acwing.com/solution/content/67450/

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

## 题目

![image-20231209232942149](image/1.9 单调队列优化的DP问题/image-20231209232942149.png)
<img src="image/1.9 单调队列优化的DP问题/image-20231209232942149.png" alt="image-20231209232942149" style="zoom:80%;" />

#### 1. [最大子序和](https://www.acwing.com/problem/content/137/)

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
64 changes: 61 additions & 3 deletions 算法提高/2. 搜索/2.1 BFS.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,67 @@ Flood Fill算法既可以用深搜实现,也可以用宽搜实现,但是为
#### 1. [池塘计数](http://ybt.ssoier.cn:8088/problem_show.php?pid=1249)

- 思路:Flood Fill 秒了

- [代码](E:\codes\C++\AcwingTest\池塘计数.cpp)

```c++
#include <iostream>
#include <algorithm>
#include <cstring>
#define x first
#define y second

using namespace std;

typedef pair<int, int> PII;

const int N = 1010, M = N * N;

int n, m;
char g[N][N];
bool st[N][N];
PII q[M]; // 队列

void bfs(int sx, int sy)
{
int hh = 0, tt = 0;
q[0] = {sx, sy};
st[sx][sy] = true;
while (hh <= tt)
{
PII t = q[hh ++ ];
// 遍历8个方向
for (int i = t.x - 1; i <= t.x + 1; i ++ )
for (int j = t.y - 1; j <= t.y + 1; j ++ )
{
if (i == t.x && j == t.y) continue; // 特判掉中间那个点
if (i < 0 || i >= n || j < 0 || j >= m) continue;
if (g[i][j] == '.' || st[i][j]) continue;
q[ ++ tt] = {i, j};
st[i][j] = true;
}
}
}

signed main()
{
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i ++ ) scanf("%s", g[i]);

int cnt = 0;
for (int i = 0; i < n; i ++ )
for (int j = 0; j < m; j ++ )
if (g[i][j] == 'W' && !st[i][j])
{
bfs(i, j);
cnt ++ ;
}

printf("%d\n", cnt);

return 0;
}
```
****
#### 2. [城堡问题](http://ybt.ssoier.cn:8088/problem_show.php?pid=1250)
Expand Down Expand Up @@ -125,7 +183,7 @@ BFS秒了。详见代码。
相当于给定一张无向图,图中只有两种边:边权是0 和 边权是1 的边。求图中从起点到终点的最短路径。
注意:图中有一半的点是永远不可能到达的。![image-20231229125053339](image/2.1 BFS/image-20231229125053339.png)
注意:图中有一半的点是永远不可能到达的。<img src="image/2.1 BFS/image-20231229125053339.png" alt="image-20231229125053339" style="zoom:80%;" />
**无解当且仅当起点和终点的奇偶性不同。**
Expand Down Expand Up @@ -236,7 +294,7 @@ while (!q.empty())

- **`A*`算法不能保证除了终点外的其他点的第一次出队的时候的距离最短。**

![image-20231231132623644](image/2.1 BFS/image-20231231132623644.png)
<img src="image/2.1 BFS/image-20231231132623644.png" alt="image-20231231132623644" style="zoom:80%;" />

- `A*`算法与其他算法的不同之处:**每次出队的时候不是判重而是更新距离**。只有终点第一次出队才是正确的,其他点出队一次就要更新一次。`BFS`是在入队的时候判重,`Dijkstra`在出队的时候判重,`A*`不能判重。

Expand Down
6 changes: 3 additions & 3 deletions 算法提高/2. 搜索/2.2 DFS.md
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ DFS的时间复杂度都不太好算,反正是指数级别就对了。上述

与双向BFS思想一样,若搜索范围特别庞大,从起点想要搜到终点耗时特别长,此时就需要终点往起点搜,也就是双向搜索。

![image-20240101204045909](image/2.2 DFS/image-20240101204045909.png)
<img src="image/2.2 DFS/image-20240101204045909.png" alt="image-20240101204045909" style="zoom:80%;" />

这样,搜索的范围就是绿色部分,剪掉了红色部分范围,大大提高效率。

Expand Down Expand Up @@ -270,7 +270,7 @@ DFS的时间复杂度都不太好算,反正是指数级别就对了。上述
- **优化搜索顺序**:将每个数从大到小排序,优先搜索较大的数。
- 可行性剪枝:当重量之和大于W时,剪掉该分支。

![image-20240102000019100](image/2.2 DFS/image-20240102000019100.png)
<img src="image/2.2 DFS/image-20240102000019100.png" alt="image-20240102000019100" style="zoom:80%;" />

- [代码](E:\codes\C++\AcwingTest\送礼物.cpp)
- Update: 数据加强了,$K$取$\frac{N}{2}$才能AC。
Expand All @@ -295,7 +295,7 @@ DFS的时间复杂度都不太好算,反正是指数级别就对了。上述

- 如何用`IDA*`来做?

![image-20240102114603782](image/2.2 DFS/image-20240102114603782.png)
<img src="image/2.2 DFS/image-20240102114603782.png" alt="image-20240102114603782" style="zoom:80%;" />

思考每次操作会修改哪些数的**后继关系**

Expand Down
Loading

0 comments on commit ea83c05

Please sign in to comment.