Skip to content

Commit

Permalink
add
Browse files Browse the repository at this point in the history
  • Loading branch information
hs867785578 committed Aug 19, 2023
1 parent 47a40d9 commit fe02883
Show file tree
Hide file tree
Showing 24 changed files with 361 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ int main(){
- 静态数据成员可以被初始化,但是只能在类体外进行初始化,若未对静态数据成员赋初值,则编译器会自动为其初始化为 0。
- 静态成员变量使用前必须先在类外初始化(如 int MyClass::m_nNumber = 0;),否则会在 linker 时出错。但是如果是const static变量,就可以在类内初始化,因为所有类都有这个变量且不可变。(C++17之前)。C++17 之后,inline可以直接修饰变量(之前只可以修饰函数),可以在类内通过static inline 直接进行声明与初始化,也可以在类内部进行声明,在类外(但是在头文件中)通过inline 进行初始化。其实就是**新标准通过inline能够保证类内静态变量只初始化一次,全局共享一份数据**,而之前的标准是不允许inline修饰类的静态成员变量的;在c++17开始,constexpr包含inline含义。
- **静态成员变量使用前必须先在类外初始化**(如 int MyClass::m_nNumber = 0;),否则会在 linker 时出错。但是**如果是const static变量,就可以在类内初始化**,因为所有类都有这个变量且不可变。(C++17之前)。C++17 之后,inline可以直接修饰变量(之前只可以修饰函数),可以在类内通过static inline 直接进行声明与初始化,也可以在类内部进行声明,在类外(但是在头文件中)通过inline 进行初始化。其实就是**新标准通过inline能够保证类内静态变量只初始化一次,全局共享一份数据**,而之前的标准是不允许inline修饰类的静态成员变量的;在c++17开始,constexpr包含inline含义。
```cpp
class MyClass
{
Expand All @@ -59,14 +59,14 @@ inline MyClass myGlobalObj; // OK even if included/defined by multiple CPP files
```


- 静态数据成员既可以通过对象名引用,也可以通过类名引用。
- 静态数据成员**既可以通过对象名引用,也可以通过类名引用**

### 2.5 类中的静态成员函数
被 static 修饰的方法属于类方法,可以通过类名.方法名直接引用,而不需要 new 出一个类来。
- 类的对象可以使用静态成员函数和非静态成员函数。但是静态成员函数不能调用非静态成员变量(因为非静态成员变量还没有分配内存,实例化后才分配内存)
- 类的非静态成员函数可以调用用静态成员函数,但反之不能。
- 非静态成员函数有 this 指针,而静态成员函数没有 this 指针
- 总结:非静态可以调用静态,但是静态不可以调用非静态。
- **总结:非静态可以调用静态,但是静态不可以调用非静态。**


## 3 extern的用法:
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.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/其他笔记/images/刷题记录_image_7.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
153 changes: 111 additions & 42 deletions docs/其他笔记/刷题记录.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,21 @@ https://perper.site/2019/01/21/C-%E5%88%B7%E9%A2%98%E5%B8%B8%E7%94%A8%E6%95%B0%E
用空间换时间,用一个数组来保存中间变量,最重要的是要找到递推公式。
**动态规划五部曲:**
1. 确定dp数组(dp table)以及下标的含义
2. 确定递推公式
3. dp数组如何初始化
4. 确定遍历顺序
5. 举例推导dp数组
### 1.2leetcode常见题型
[70. 爬楼梯](https://leetcode.cn/problems/climbing-stairs/)
[53. 最大子数组和](https://leetcode.cn/problems/maximum-subarray/)
[1143. 最长公共子序列](https://leetcode.cn/problems/longest-common-subsequence/)
[5. 最长回文子串](https://leetcode.cn/problems/longest-palindromic-substring/)
## 2DFS(深度优先搜索)
## 2 DFS(深度优先搜索)
### 2.1基本套路
Expand Down Expand Up @@ -362,6 +369,30 @@ public:

本质上回溯=穷举+剪枝

回溯能够解决:组合、切割、子集、排列等问题。**所有的回溯问题都可以抽象为一棵树!**

**回溯三部曲:**
1. 确定回溯函数模板返回值以及参数
2. 确定终止条件(纵向)
3. 回溯遍历(横向)

注意:回溯的参数中一定要有res,cur的引用。在终止条件满足时,res.push_back(cur)

**模板:**
```cpp
void backtracking(参数) {
if (终止条件) {
存放结果;
return;
}

for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {//横向
处理节点;
backtracking(路径,选择列表); // 递归,纵向
回溯,撤销处理结果
}
}
```
### 4.1 回溯和递归的区别
**递归是一种算法结构**。递归会出现在子程序中,形式上表现为直接或间接的自己调用自己。典型的例子是阶乘,计算规律为:n!=n×(n−1)!,如果用 C++ 代码表示,基本如下所示:
Expand Down Expand Up @@ -695,51 +726,89 @@ public:
```
## 7路径规划算法
- Dijkstra和A\*的统一伪代码
![](images/刷题记录_image_5.png)
![](images/刷题记录_image_6.png)
### Dijkstra
```cpp
struct Node
{
int num; //编号
int d; //起点s到达num的最短路程
friend bool operator < (const Node &a, const Node &b)
{
return a.d > b.d; //重载<运算符,令d小的优先度高
}
};
https://zhuanlan.zhihu.com/p/360276556
int N, G[maxn][maxn] = { 0 };
int d[maxn], pre[maxn];
bool vis[maxn] = { false };
三个量分别需要定义:
- `priority_queue<PII, vector<PII>, decltype(gt)> q(gt);//{node,distance}`
- `vector<int> distance(N, INT_MAX);`
- `vector<int> vis(N, 0);`
void Dijkstra(int s)
{
fill(d, d + maxn, INF);
fill(pre, pre + maxn, -1);
d[s] = 0;
priority_queue<Node> q;
Node t = { s,d[s] };
q.push(t);
while (!q.empty())
{
int u = q.top().num; //取当前队首结点u
q.pop();
if(vis[u]) //若u已被访问过,说明当前 d并不是最小值,直接跳过
continue;
else
vis[u] = true; //否则对 u进行访问
for (int v = 0; v < N; v++) //以 u为踏板优化 u能直接到达 的结点v
{
if (!vis[v] && G[u][v] && d[u] + G[u][v] < d[v])
{
d[v] = d[u] + G[u][v];
pre[v] = u;
t.num=v;
t.d=d[v];
q.push(t);
}
}
初始化:
- `distance[src] = 0;`
- vis初始化为0
- `q.push({src, distance[src]});`
```c++
using PII = pair<int, int>;
//邻接表 key = src ,val = {adj,cost}
int dijkstra (unordered_map<int, vector<PII>>& graph, int src, int tar, int N) {
auto gt = [](auto& a, auto& b) { return a.second > b.second; };
priority_queue<PII, vector<PII>, decltype(gt)> q(gt);//{node,distance}
vector<int> distance(N, INT_MAX);
distance[src] = 0;
vector<int> vis(N, 0);
q.push({src, distance[src]});
while(!q.empty()) {
auto [node, dis] = q.top();
q.pop();
if (vis[node]) continue;
vis[node] = 1;
for (auto& [adj, cost] : graph[node]) {
if (distance[adj] > distance[node] + cost) {
distance[adj] = distance[node] + cost;
q.push({adj, distance[adj]});
}
}
}
}
return distance[tar] == INT_MAX ? -1 : distance[tar];
```

### a star

https://zhuanlan.zhihu.com/p/360282185

- 优先队列存储的是actual+heuristic distance,不再是actua distance
- distance数组不再是vector\<int\>,而变为`vector<pair<int, int>>`存actual 和 heuristic distance
- 其他不变

```cpp
using PII = pair<int, int>;

// 启发式函数,估计从当前节点到目标节点的距离
int h(int node, int tar) {
// 根据实际情况编写启发式函数
// 例如,可以使用曼哈顿距离或欧几里得距离
//如果返回0,则等价于dijkstra
}

int astar(unordered_map<int, vector<PII>>& graph, int src, int tar, int N) {
auto gt = [](auto& a, auto& b) { return a.second > b.second; };
priority_queue<PII, vector<PII>, decltype(gt)> q(gt); // {node, actual+heuristic distance}
vector<pair<int, int>> distance(N, {INT_MAX, 0}); // {actual distance, heuristic distance}
distance[src] = {0, h(src, tar)}; // 初始化起始节点的距离
vector<int> vis(N, 0);
q.push({src, distance[src].first + distance[src].second}); // 综合评估值为实际距离加启发式函数估计距离

while (!q.empty()) {
auto [node, dis] = q.top();
q.pop();
if (vis[node]) continue;
vis[node] = 1;
for (auto& [adj, cost] : graph[node]) {
if (distance[adj].first > distance[node].first + cost) {
distance[adj].first = distance[node].first + cost;
distance[adj].second = distance[adj].first + h(adj, tar); // 更新启发式函数估计距离
q.push({adj, distance[adj].first + distance[adj].second});
}
}
}

return distance[tar].first == INT_MAX ? -1 : distance[tar].first;
}
```
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/数学/images/判断是否相交_image_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
106 changes: 106 additions & 0 deletions docs/数学/判断是否相交.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@

## 判断两个线段是否相交

快速排斥+跨立实验
### 快速排斥实验

我们首先判断两条线段在 x 以及 y 坐标的投影是否有重合。 
也就是判断下一个线段中 x 较大的端点是否小于另一个线段中 x 较小的段点,若是,则说明两个线段必然没有交点,同理判断下 y。

![这里写图片描述](https://img-blog.csdn.net/20170428142226521?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXE4MjYzMDkwNTc=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast) 
如上图所示,代码表示如下:

```cpp
max(C.x,D.x)<min(A.x,B.x) || max(C.y,D.y)<min(A.y,B.y) ||max(A.x,B.x)<min(C.x,D.x) || max(A.y,B.y)<min(C.y,C.y)
```
### 跨立实验
对于两个向量:P = (x1, y1),Q = ( x2, y2 ),矢量叉积定义为:P × Q = x1*y2 - x2*y1。
叉积的一个非常重要性质是可以通过它的符号判断两矢量相互之间的顺逆时针关系: 
  若 P × Q > 0 , 则 P 在 Q 的顺时针方向。 
  若 P × Q < 0 , 则 P 在 Q 的逆时针方向。 
  若 P × Q = 0 , 则 P 与 Q 共线,但可能同向也可能反向。
跨立实验原理,主要原理:
进行叉积运算,向量AC×向量AB,向量AD×向量AB,如果两个向量(AC,AD)都排在两边,那么两个结果则分别指向纸内和纸外,这样,**将上面叉积的结果进行点积运算,就可以得到一个负值**。
当最终点积等于0的时候,说明两条重合,这时也符合条件(由于通过了第一步的快速排斥实验)
交换两条直线,同理。
综上,最终点积小于0的情况为两条直线相交的情况。
```cpp
// An highlighted block
#include<iostream>
using namespace std;
struct Line {
double x1;
double y1;
double x2;
double y2;
};
// 快速排斥实验 Rapid rejection experiments
bool RapidRejExper(Line& l1, Line& l2) {
if ((l1.x1 > l1.x2 ? l1.x1 : l1.x2) < (l2.x1 < l2.x2 ? l2.x1 : l2.x2) ||
(l1.y1 > l1.y2 ? l1.y1 : l1.y2) < (l2.y1 < l2.y2 ? l2.y1 : l2.y2) ||
(l2.x1 > l2.x2 ? l2.x1 : l2.x2) < (l1.x1 < l1.x2 ? l1.x1 : l1.x2) ||
(l2.y1 > l2.y2 ? l2.y1 : l2.y2) < (l1.y1 < l1.y2 ? l1.y1 : l1.y2)) {
return false;
}
return true;
}
// 跨立实验
bool Cross(Line& l1, Line& l2) {
if ((((l1.x1 - l2.x1) * (l2.y2 - l2.y1) - (l1.y1 - l2.y1) * (l2.x2 - l2.x1)) *
((l1.x2 - l2.x1) * (l2.y2 - l2.y1) - (l1.y2 - l2.y1) * (l2.x2 - l2.x1))) > 0 ||
(((l2.x1 - l1.x1) * (l1.y2 - l1.y1) - (l2.y1 - l1.y1) * (l1.x2 - l1.x1)) *
((l2.x2 - l1.x1) * (l1.y2 - l1.y1) - (l2.y2 - l1.y1) * (l1.x2 - l1.x1))) > 0)
{
return false;
}
return true;
}
int main() {
Line l1, l2;
cin >> l1.x1 >> l1.y1 >> l1.x2 >> l1.y2;
cin >> l2.x1 >> l2.y1 >> l2.x2 >> l2.y2;
if (RapidRejExper(l1, l2) && Cross(l1, l2)) {
cout << "Yes";
}
else {
cout << "No";
}
}
```



## 判断两个矩形是否相交

### 不考虑旋转(AA-BOX):
![](images/判断是否相交_image_1.png)

反向考虑:如果不相交只有四种情况:

A在B的左边 (A.r < B.x)
A在B的右边 ( B.r < A.x)
A在B的上边 (A.b < B.y )
A在B的下边 (B.b < A.y )

上述四个条件,只要满足一个就不相交。因此取或:
A.r < B.x || B.r < A.x || A.b < B.y || B.b <A.y

取反就是相交:
!(A.r < B.x || B.r < A.x || A.b < B.y || B.b <A.y)

### 考虑旋转:

GJK等方法


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.
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.
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.
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.
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.
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.
Loading

0 comments on commit fe02883

Please sign in to comment.