Altered
This commit is contained in:
66
Algorithm/Graph/BFS/Maze.cpp
Normal file
66
Algorithm/Graph/BFS/Maze.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
#include <deque>
|
||||
using namespace std;
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
int dx[4] = {0, 0, -1, 1};
|
||||
int dy[4] = {1, -1, 0, 0};
|
||||
int dxx[8] = {-1, -1, -1, 0, 0, 1, 1, 1};
|
||||
int dyy[8] = {1, 0, -1, 1, -1, 1, 0, -1};
|
||||
int main(){
|
||||
deque<pair<int, int>> q;
|
||||
int n, m;
|
||||
//<2F><><EFBFBD><EFBFBD>
|
||||
cin >> n >> m;
|
||||
int startx, starty;
|
||||
//<2F><><EFBFBD><EFBFBD>
|
||||
cin >> startx >> starty;
|
||||
|
||||
deque<deque<int>> maze;
|
||||
deque<deque<bool>> visited;
|
||||
deque<deque<int>> dist(n, deque<int>(m, 0)); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
maze.resize(n);
|
||||
visited.resize(n, deque<bool>(m, false));
|
||||
int tmp;
|
||||
//0<><30>ʾǽ<CABE><C7BD>1<EFBFBD><31>ʾ·
|
||||
for(int i = 0; i < n; i++){
|
||||
for(int j = 0; j < m; j++){
|
||||
cin >> tmp;
|
||||
maze[i].push_back(tmp);
|
||||
}
|
||||
}
|
||||
tmp = 0;
|
||||
q.push_back(make_pair(startx, starty));
|
||||
while(!q.empty()){
|
||||
pair<int, int> u = q.front();
|
||||
q.pop_front();
|
||||
int x = u.first, y = u.second;
|
||||
visited[x][y] = true;
|
||||
|
||||
for(int i = 0; i < 4; i++){
|
||||
if(x + dx[i] >= 0 && x + dx[i] < n && y + dy[i] >= 0 && y + dy[i] < m && !visited[x + dx[i]][y + dy[i]] && maze[x + dx[i]][y + dy[i]] == 1){
|
||||
visited[x + dx[i]][y + dy[i]] = true;
|
||||
dist[x + dx[i]][y + dy[i]] = dist[x][y] + 1; // <20><><EFBFBD>¾<EFBFBD><C2BE><EFBFBD>
|
||||
q.push_back(make_pair(x + dx[i], y + dy[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
cout << endl;
|
||||
for(int i = 0; i < n; i++){
|
||||
for(int j = 0; j < m; j++){
|
||||
cout << dist[i][j] << " ";
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
6 5
|
||||
0 0
|
||||
1 1 0 1 1
|
||||
1 0 1 1 1
|
||||
1 0 1 0 0
|
||||
1 0 1 1 1
|
||||
1 1 1 0 1
|
||||
1 1 1 1 1
|
||||
*/
|
||||
63
Algorithm/Graph/DFS/UVa10603-Fill.cpp
Normal file
63
Algorithm/Graph/DFS/UVa10603-Fill.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <bits/stdc++.h>
|
||||
using namespace std;
|
||||
|
||||
bool have = false;
|
||||
set<tuple<int,int,int>> visited;
|
||||
|
||||
int A, B, C; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
void dfs(int a, int b, int c, int target) {
|
||||
if (a == target || b == target || c == target) {
|
||||
have = true;
|
||||
return;
|
||||
}
|
||||
|
||||
auto state = make_tuple(a, b, c);
|
||||
if (visited.find(state) != visited.end()) return;
|
||||
visited.insert(state);
|
||||
|
||||
// <20><><EFBFBD>ֵ<EFBFBD>ˮ<EFBFBD><CBAE><EFBFBD><EFBFBD>
|
||||
// a -> b
|
||||
{
|
||||
int pour = min(a, B - b);
|
||||
dfs(a - pour, b + pour, c, target);
|
||||
}
|
||||
// a -> c
|
||||
{
|
||||
int pour = min(a, C - c);
|
||||
dfs(a - pour, b, c + pour, target);
|
||||
}
|
||||
// b -> a
|
||||
{
|
||||
int pour = min(b, A - a);
|
||||
dfs(a + pour, b - pour, c, target);
|
||||
}
|
||||
// b -> c
|
||||
{
|
||||
int pour = min(b, C - c);
|
||||
dfs(a, b - pour, c + pour, target);
|
||||
}
|
||||
// c -> a
|
||||
{
|
||||
int pour = min(c, A - a);
|
||||
dfs(a + pour, b, c - pour, target);
|
||||
}
|
||||
// c -> b
|
||||
{
|
||||
int pour = min(c, B - b);
|
||||
dfs(a, b + pour, c - pour, target);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
int target;
|
||||
cin >> A >> B >> C >> target;
|
||||
dfs(A, 0, 0, target); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC> A װ<><D7B0>
|
||||
if (have) cout << "YES" << endl;
|
||||
else cout << "NO" << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
32
Algorithm/Graph/DFS/UVa1600Knight-Move betteruseBSF.cpp
Normal file
32
Algorithm/Graph/DFS/UVa1600Knight-Move betteruseBSF.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
//ab<61><62><EFBFBD>յ<EFBFBD>
|
||||
int dx[8] = {-2, -1, 1, 2, 2, 1, -1, -2};
|
||||
int dy[8] = {1, 2, 2, 1, -1, -2, -2, -1};
|
||||
int step[9][9];
|
||||
|
||||
void dfs(int _a, int _b, int _n, int _m){
|
||||
if(_n > 8 || _n < 1 || _m < 1 || _m > 8) return;
|
||||
if(_n == _a && _m == _b) return;
|
||||
for(int i = 0; i < 8; i++){
|
||||
int nx = _n + dx[i];
|
||||
int ny = _m + dy[i];
|
||||
|
||||
if (nx >= 1 && nx <= 8 && ny >= 1 && ny <= 8) {
|
||||
int stepnew = step[_n][_m] + 1;
|
||||
if (step[nx][ny] == 0 || stepnew < step[nx][ny]) {
|
||||
step[nx][ny] = stepnew;
|
||||
dfs(_a, _b, nx, ny);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(){
|
||||
int a, b, n, m;
|
||||
cin >> n >> m >> a >> b;
|
||||
step[n][m] = 0;
|
||||
dfs(a, b, n, m);
|
||||
cout << step[a][b] << endl;
|
||||
return 0;
|
||||
}
|
||||
51
Algorithm/Graph/DFS/UVa572-Oil-Deposits.cpp
Normal file
51
Algorithm/Graph/DFS/UVa572-Oil-Deposits.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
int m = 5, n = 5;
|
||||
vector<vector<char>> s;
|
||||
vector<vector<bool>> visited;
|
||||
vector<vector<int>> ids;
|
||||
|
||||
|
||||
void dfs(int x, int y, int id){
|
||||
if(x < 0 || x >= m || y < 0 || y >=n) return;
|
||||
if(s[x][y] != '@') return;
|
||||
if(visited[x][y] == true) return;
|
||||
visited[x][y] = true;
|
||||
ids[x][y] = id;
|
||||
dfs(x - 1, y - 1, id + 1);
|
||||
dfs(x - 1, y, id + 1);
|
||||
dfs(x - 1, y + 1, id + 1);
|
||||
dfs(x, y - 1, id + 1);
|
||||
dfs(x, y + 1, id + 1);
|
||||
dfs(x + 1, y - 1, id + 1);
|
||||
dfs(x + 1, y, id + 1);
|
||||
dfs(x + 1, y + 1, id + 1);
|
||||
cout << id << " ";
|
||||
}
|
||||
|
||||
int main(){
|
||||
s.resize(m);
|
||||
visited.assign(m, vector<bool>(n, false));
|
||||
ids.assign(m, vector<int>(n, 0));
|
||||
char tmp;
|
||||
for(int i = 0; i < m; i++){
|
||||
for(int j = 0; j < n; j++){
|
||||
cin >> tmp;
|
||||
s[i].push_back(tmp);
|
||||
}
|
||||
}
|
||||
for(int i = 0; i < m; i++){
|
||||
for(int j = 0; j < n; j++){
|
||||
if(!visited[i][j] && s[i][j] == '@') dfs(i, j, 1);
|
||||
}
|
||||
}
|
||||
cout << endl;
|
||||
int max = -1;
|
||||
for(int i = 0; i < m; i++){
|
||||
for(int j = 0; j < n; j++){
|
||||
if(ids[i][j] > max) max = ids[i][j];
|
||||
}
|
||||
}
|
||||
cout << max << endl;
|
||||
}
|
||||
40
Algorithm/Graph/DFS/UVa673-Parentheses-Balance([]).cpp
Normal file
40
Algorithm/Graph/DFS/UVa673-Parentheses-Balance([]).cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
//确定每个节点要干什么
|
||||
bool dfs(const string& s, int l, int r) {
|
||||
if (l > r) return true; // 空串平衡
|
||||
if (l == r) return false; // 单个字符不平衡
|
||||
|
||||
// 必须匹配类型
|
||||
char open = s[l];
|
||||
char close = (open == '(') ? ')' : (open == '[') ? ']' : 0;
|
||||
if (close == 0) return false; // 非括号字符
|
||||
|
||||
int cnt = 0;
|
||||
int p = -1;
|
||||
for (int i = l; i <= r; i++) {
|
||||
if (s[i] == '(' || s[i] == '[') cnt++;
|
||||
if (s[i] == ')' || s[i] == ']') cnt--;
|
||||
if (cnt == 0) {
|
||||
p = i; // 找到匹配的右括号
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (p == -1) return false; // 没找到匹配
|
||||
if (s[p] != close) return false; // 类型不匹配(第一个和最后一个字符匹配)
|
||||
|
||||
// 内部和剩余区间递归
|
||||
return dfs(s, l + 1, p - 1) && dfs(s, p + 1, r);
|
||||
}
|
||||
|
||||
int main(){
|
||||
string a;
|
||||
while(true)
|
||||
{
|
||||
cin >> a;
|
||||
dfs(a, 0, a.size() - 1) ? cout << "YES" << endl : cout << "NO" << endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
80
Algorithm/Graph/EulerGraph/UVa-10129-PlayOnWords.cpp
Normal file
80
Algorithm/Graph/EulerGraph/UVa-10129-PlayOnWords.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
struct Graph{
|
||||
int v;
|
||||
int e;
|
||||
vector<vector<int>> adj;
|
||||
vector<bool> visited;
|
||||
|
||||
Graph(int _v) : v(_v) {
|
||||
adj.resize(v);
|
||||
visited.assign(v, false);
|
||||
}
|
||||
bool validateV(int _v){
|
||||
return ( _v >= 0 && _v < v);
|
||||
}
|
||||
void insert(int _a, int _b){
|
||||
if(!validateV(_a) || !validateV(_b)) return;
|
||||
|
||||
adj[_a].push_back(_b);
|
||||
}
|
||||
int degree(int _v){
|
||||
if(!validateV(_v)) return 0;
|
||||
return outDegree(_v) + inDegree(_v);
|
||||
}
|
||||
int outDegree(int _v){
|
||||
if(!validateV(_v)) return 0;
|
||||
return adj[_v].size();
|
||||
}
|
||||
int inDegree(int _v){
|
||||
if(!validateV(_v)) return 0;
|
||||
int js = 0;
|
||||
for(auto x : adj){
|
||||
for(int i = 0; i < x.size(); i++){
|
||||
if(x[i] == _v) js++;
|
||||
}
|
||||
}
|
||||
return js;
|
||||
}
|
||||
void dfs(int _v){
|
||||
if(!validateV(_v)) return;
|
||||
if(visited[_v]) return;
|
||||
visited[_v] = true;
|
||||
for(auto x : adj[_v]){
|
||||
dfs(x);
|
||||
}
|
||||
}
|
||||
bool isConnected(){
|
||||
dfs(0);
|
||||
for(auto x : visited){
|
||||
if(!x) return false;
|
||||
}
|
||||
|
||||
int js = 0;
|
||||
for(int i = 0; i < v; i++){
|
||||
if(degree(i) % 2 == 1) js++;
|
||||
}
|
||||
return (js == 0) || (js == 2);
|
||||
}
|
||||
};
|
||||
int main(){
|
||||
int n;
|
||||
cin >> n;
|
||||
Graph g(n);
|
||||
vector<string> s;
|
||||
s.resize(n);
|
||||
for(int i = 0; i < n; i++){
|
||||
cin >> s[i];
|
||||
}
|
||||
for(int i = 0; i < n; i++){
|
||||
for(int j = 0; j < n; j++){
|
||||
if(i != j && s[i].back() == s[j].front()) g.insert(i, j);
|
||||
}
|
||||
}
|
||||
g.isConnected() ? cout << "YES" << endl : cout << "NO" << endl;
|
||||
system("pause");
|
||||
return 0;
|
||||
}
|
||||
85
Algorithm/Graph/Tree/表达式树/readme.md
Normal file
85
Algorithm/Graph/Tree/表达式树/readme.md
Normal file
@@ -0,0 +1,85 @@
|
||||
好的 👍 我来总结一下 **生成表达式树** 的常见方法(只讲思路,不上代码):
|
||||
|
||||
---
|
||||
|
||||
## 1. **基于后缀表达式(逆波兰式)**
|
||||
|
||||
这是最常见也最简单的方法。
|
||||
|
||||
* **步骤**:
|
||||
|
||||
1. 先把中缀表达式(如 `3 + 5 * 2`)转为后缀表达式(`3 5 2 * +`),通常用 **栈** 实现。
|
||||
2. 遍历后缀表达式:
|
||||
|
||||
* 遇到操作数(数字/变量),创建一个叶子节点,压入栈。
|
||||
* 遇到运算符,弹出两个节点(右操作数在栈顶),生成一个新运算符节点,把两个节点作为它的左右子树,再把这个新节点压入栈。
|
||||
3. 最后栈中唯一的节点就是整棵表达式树的根。
|
||||
* **优点**:逻辑清晰,栈结构天然适合。
|
||||
* **应用**:编译器、计算器。
|
||||
|
||||
---
|
||||
|
||||
## 2. **基于递归下降 / 文法解析**
|
||||
|
||||
* 将表达式看作一棵语法树,利用递归来解析。
|
||||
* **例子**:
|
||||
|
||||
* 一个表达式 `E` 可以分为:`E = T (+/- T)*`
|
||||
* 一个项 `T` 可以分为:`T = F (*// F)*`
|
||||
* 一个因子 `F` 可以是:数字 / 变量 / 括号里的子表达式
|
||||
* 递归解析时,每一层返回一个子树节点,最后拼成完整的树。
|
||||
* **优点**:结构清晰,和正规语法(BNF)一一对应。
|
||||
* **应用**:编译器前端、解释器。
|
||||
|
||||
---
|
||||
|
||||
## 3. **运算符优先级栈法(Shunting-yard)**
|
||||
|
||||
* 由 Dijkstra 提出的著名算法,本质是把中缀转后缀(再转树)。
|
||||
* **步骤**:
|
||||
|
||||
1. 准备两个栈:运算符栈、操作数栈。
|
||||
2. 依次读入符号:
|
||||
|
||||
* 数字 → 压入操作数栈。
|
||||
* 运算符 → 根据优先级处理,出栈已有运算符并生成树节点。
|
||||
* 括号 → 特殊处理。
|
||||
3. 最终把所有运算符出栈,并拼接成树。
|
||||
* **优点**:不必先生成后缀表达式,直接就能建树。
|
||||
* **应用**:表达式求值、解释器。
|
||||
|
||||
---
|
||||
|
||||
## 4. **自顶向下(分治法)**
|
||||
|
||||
* 如果你能快速找到当前表达式中 **优先级最低的主运算符**(比如在 `(3+5)*2` 中的 `*`),就可以:
|
||||
|
||||
1. 把它作为根节点。
|
||||
2. 左右部分递归生成子树。
|
||||
* **例子**:
|
||||
|
||||
* 表达式 `3 + 5 * 2 - 4`
|
||||
* 最外层的最低优先级是 `+` 和 `-`,最右的 `-` 成为根
|
||||
* 左边 `3+5*2` 递归成一棵子树,右边 `4` 变叶子
|
||||
* **优点**:直观,完全递归化。
|
||||
* **缺点**:实现时需要小心括号和优先级。
|
||||
|
||||
---
|
||||
|
||||
## 5. **抽象语法树 (AST) 生成**
|
||||
|
||||
* 在编译原理里,语法分析器(Parser)生成的就是 **AST**,本质上就是表达式树。
|
||||
* 一般通过 **词法分析 → 语法分析**,然后根据语法规则建树。
|
||||
* **特点**:相比一般表达式树,AST 会忽略括号、某些中间节点,只保留运算逻辑。
|
||||
|
||||
---
|
||||
|
||||
📌 **总结**:
|
||||
|
||||
* 如果是实际写程序 → 推荐 **方法 1(后缀表达式 + 栈)** 或 **方法 3(Shunting-yard)**。
|
||||
* 如果是研究语法 / 编译原理 → 用 **方法 2(递归下降)** 或 **方法 5(AST 生成)**。
|
||||
* 如果只是想理解表达式结构 → **方法 4(分治法)** 最直观。
|
||||
|
||||
---
|
||||
|
||||
要不要我帮你画几个 **同一个表达式在不同方法下生成的树的对比图**?
|
||||
100
Algorithm/Graph/Tree/表达式树/后缀分治.cpp
Normal file
100
Algorithm/Graph/Tree/表达式树/后缀分治.cpp
Normal file
@@ -0,0 +1,100 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
template <class T>
|
||||
struct Node{
|
||||
T element;
|
||||
Node<T>* left;
|
||||
Node<T>* right;
|
||||
|
||||
Node() : element(-1), left(nullptr), right(nullptr) {}
|
||||
Node(T x) : element(x), left(nullptr), right(nullptr) {}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct Tree{
|
||||
Node<T>* root;
|
||||
|
||||
Tree() : root(nullptr) {}
|
||||
Tree(Node<T>* x) : root(x) {}
|
||||
void inOrder(Node<T>* x){
|
||||
if(!x) return;
|
||||
inOrder(x->left);
|
||||
cout << x->element << " ";
|
||||
inOrder(x->right);
|
||||
}
|
||||
void preOrder(Node<T>* x){
|
||||
if(!x) return;
|
||||
cout << x->element << " ";
|
||||
preOrder(x->left);
|
||||
preOrder(x->right);
|
||||
}
|
||||
void postOrder(Node<T>* x){
|
||||
if(!x) return;
|
||||
postOrder(x->left);
|
||||
postOrder(x->right);
|
||||
cout << x->element << " ";
|
||||
}
|
||||
};
|
||||
|
||||
bool checky(char s){
|
||||
if(s == '+' || s == '-' || s == '*' || s == '/') return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
int checkb(char s){
|
||||
if(s == '(') return 1;
|
||||
if(s == ')') return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//[x, y)
|
||||
template <class T>
|
||||
Node<T>* build(const string& s, const int& x, const int& y){
|
||||
if ((y - x) == 1) return new Node<T>(s[x]);
|
||||
|
||||
// ȥ<><C8A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
if (s[x] == '(' && s[y-1] == ')') {
|
||||
int cnt = 0; bool ok = true;
|
||||
for (int i = x; i < y; i++) {
|
||||
if (s[i] == '(') cnt++;
|
||||
if (s[i] == ')') cnt--;
|
||||
if (cnt == 0 && i < y-1) { ok = false; break; }
|
||||
}
|
||||
if (ok) return build<T>(s, x+1, y-1);
|
||||
}
|
||||
|
||||
// <20><><EFBFBD><EFBFBD>ɨ<EFBFBD>裺<EFBFBD><E8A3BA> +-<2D><><EFBFBD><EFBFBD> */
|
||||
for (int pass = 0; pass < 2; pass++) {
|
||||
int js = 0;
|
||||
for (int i = y-1; i >= x; i--) {
|
||||
js += checkb(s[i]);
|
||||
if (checky(s[i]) && js == 0) {
|
||||
if ((pass == 0 && (s[i] == '+' || s[i] == '-')) ||
|
||||
(pass == 1 && (s[i] == '*' || s[i] == '/'))) {
|
||||
Node<T>* tmp = new Node<T>(s[i]);
|
||||
tmp->right = build<T>(s, i+1, y);
|
||||
tmp->left = build<T>(s, x, i);
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int main(){
|
||||
string a;
|
||||
cin >> a;
|
||||
Node<char>* root = build<char>(a, 0, a.size());
|
||||
Tree<char> t(root);
|
||||
t.preOrder(root);
|
||||
cout << endl;
|
||||
t.inOrder(root);
|
||||
cout << endl;
|
||||
t.postOrder(root);
|
||||
cout << endl;
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user