Algorithm
This commit is contained in:
80
Algorithm/BackTracking/readme.md
Normal file
80
Algorithm/BackTracking/readme.md
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
回溯法(Backtracking)是一种**系统地枚举所有可能解**的方法,通常用于解决**组合、排列、约束满足等问题**。它的核心思想是:在搜索问题的解空间时,如果发现当前部分解无法得到最终解,就**立即放弃(回溯)**,避免无谓的计算。
|
||||||
|
|
||||||
|
我给你拆开讲:
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 1️⃣ 基本思路
|
||||||
|
|
||||||
|
1. 从问题的初始状态开始,尝试每一种可能的选择。
|
||||||
|
2. 对于每一种选择:
|
||||||
|
|
||||||
|
* 判断是否符合条件(约束)。
|
||||||
|
* 如果符合,就继续尝试下一步。
|
||||||
|
* 如果不符合,直接放弃(剪枝)。
|
||||||
|
3. 当到达最终状态时,把解记录下来。
|
||||||
|
4. 搜索完当前选择后,撤销选择(回到上一步),尝试其他可能。
|
||||||
|
|
||||||
|
这个“尝试→失败→撤销→尝试其他”过程就是“回溯”。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2️⃣ 典型问题
|
||||||
|
|
||||||
|
回溯法适合解决这类问题:
|
||||||
|
|
||||||
|
* **排列问题**:生成1\~n的所有排列。
|
||||||
|
* **组合问题**:从n个元素中选出k个组合。
|
||||||
|
* **子集问题**:生成所有子集。
|
||||||
|
* **棋盘类问题**:N皇后、数独、填字游戏。
|
||||||
|
* **约束满足问题**:图着色、八数码问题等。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3️⃣ 模板代码(C++示例)
|
||||||
|
|
||||||
|
以**N皇后问题**为例:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
vector<int> queens; // queens[i] = 列号
|
||||||
|
int n;
|
||||||
|
|
||||||
|
bool isValid(int row, int col) {
|
||||||
|
for(int i = 0; i < row; i++) {
|
||||||
|
int c = queens[i];
|
||||||
|
if(c == col || abs(c - col) == row - i)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void backtrack(int row) {
|
||||||
|
if(row == n) {
|
||||||
|
// 找到一个解
|
||||||
|
for(int c : queens) cout << c << " ";
|
||||||
|
cout << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for(int col = 0; col < n; col++) {
|
||||||
|
if(isValid(row, col)) {
|
||||||
|
queens.push_back(col); // 选择
|
||||||
|
backtrack(row + 1); // 递归
|
||||||
|
queens.pop_back(); // 回溯
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4️⃣ 总结
|
||||||
|
|
||||||
|
* 回溯法是一种**DFS+剪枝**的方法。
|
||||||
|
* 核心是**选择、约束、递归、撤销**。
|
||||||
|
* 常用于**枚举问题、组合问题和约束满足问题**。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
如果你愿意,我可以给你画一张**回溯法搜索树的示意图**,直观理解它是怎么“尝试、失败、回退”的。
|
||||||
|
|
||||||
|
你想让我画吗?
|
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
|
||||||
|
*/
|
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;
|
||||||
|
}
|
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;
|
||||||
|
}
|
@@ -0,0 +1,30 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <list>
|
||||||
|
#include <string>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
string line;
|
||||||
|
while (getline(cin, line)) { // һ<>ζ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD>У<EFBFBD>ֱ<EFBFBD><D6B1> EOF
|
||||||
|
list<char> s;
|
||||||
|
auto it = s.begin();
|
||||||
|
|
||||||
|
for (char tmp : line) {
|
||||||
|
if (tmp == '[') {
|
||||||
|
it = s.begin();
|
||||||
|
}
|
||||||
|
else if (tmp == ']') {
|
||||||
|
it = s.end();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
it = s.insert(it, tmp);
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (char c : s) cout << c;
|
||||||
|
cout << '\n'; // ÿ<><C3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
19
Algorithm/Maths/P1102 A-B数对/P1102 A-B 数对 set不过.cpp
Normal file
19
Algorithm/Maths/P1102 A-B数对/P1102 A-B 数对 set不过.cpp
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#include <set>
|
||||||
|
#include <iostream>
|
||||||
|
using namespace std;
|
||||||
|
int main(){
|
||||||
|
multiset<int> s;
|
||||||
|
int n, m;
|
||||||
|
cin >> n >> m;
|
||||||
|
int tmp;
|
||||||
|
for(int i = 0; i < n; i++){
|
||||||
|
cin >> tmp;
|
||||||
|
s.emplace(tmp);
|
||||||
|
}
|
||||||
|
int js = 0;
|
||||||
|
for(auto it = s.begin(); it != s.end(); it++){
|
||||||
|
js += s.count(*it - m);
|
||||||
|
}
|
||||||
|
cout << js << endl;
|
||||||
|
return 0;
|
||||||
|
}
|
26
Algorithm/Maths/P1102 A-B数对/P1102 A-B 数对 unordered_map.cpp
Normal file
26
Algorithm/Maths/P1102 A-B数对/P1102 A-B 数对 unordered_map.cpp
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
#include <iostream>
|
||||||
|
//<2F><> hash + map <20><>ԭ<EFBFBD><D4AD><EFBFBD>Dz<EFBFBD>ϣ<EFBFBD><CFA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD> O(n^2)
|
||||||
|
using namespace std;
|
||||||
|
int main(){
|
||||||
|
unordered_map<long long, int> s;
|
||||||
|
vector<long long> arr;
|
||||||
|
long long n, m;
|
||||||
|
cin >> n >> m;
|
||||||
|
long long tmp;
|
||||||
|
for(int i = 0; i < n; i++){
|
||||||
|
cin >> tmp;
|
||||||
|
arr.push_back(tmp);
|
||||||
|
s[tmp]++;
|
||||||
|
}
|
||||||
|
long long need;
|
||||||
|
long long js = 0;
|
||||||
|
for(int i = 0; i < n; i++){
|
||||||
|
need = arr[i] - m;
|
||||||
|
if(s.count(need)) js += s[need];//s[need]<5D><>ֵ<EFBFBD><D6B5> pair.seconds
|
||||||
|
//s.emplace(make_pair(arr[i], 1));//<2F><><EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD>arr[i]<5D><><EFBFBD>ڣ<EFBFBD><DAA3><EFBFBD>ֱ<EFBFBD>ӷ<EFBFBD><D3B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
}
|
||||||
|
cout << js << endl;
|
||||||
|
return 0;
|
||||||
|
}
|
BIN
Algorithm/Maths/P1102 A-B数对/P1102 A-B 数对 unordered_map.exe
Normal file
BIN
Algorithm/Maths/P1102 A-B数对/P1102 A-B 数对 unordered_map.exe
Normal file
Binary file not shown.
@@ -0,0 +1,19 @@
|
|||||||
|
#include <unordered_set>
|
||||||
|
#include <iostream>
|
||||||
|
using namespace std;
|
||||||
|
int main(){
|
||||||
|
unordered_multiset<int> s;
|
||||||
|
int n, m;
|
||||||
|
cin >> n >> m;
|
||||||
|
int tmp;
|
||||||
|
for(int i = 0; i < n; i++){
|
||||||
|
cin >> tmp;
|
||||||
|
s.emplace(tmp);
|
||||||
|
}
|
||||||
|
int js = 0;
|
||||||
|
for(auto it = s.begin(); it != s.end(); it++){
|
||||||
|
js += s.count(*it - m);
|
||||||
|
}
|
||||||
|
cout << js << endl;
|
||||||
|
return 0;
|
||||||
|
}
|
24
Algorithm/Recursion/UVA699 下落的树叶 The Falling Leaves.cpp
Normal file
24
Algorithm/Recursion/UVA699 下落的树叶 The Falling Leaves.cpp
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
|
using namespace std;
|
||||||
|
//<2F><><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD>
|
||||||
|
|
||||||
|
map<int, int> sum;
|
||||||
|
void build(int p){
|
||||||
|
int tmp;
|
||||||
|
cin >> tmp;
|
||||||
|
if(tmp == -1) return;
|
||||||
|
sum[p] += tmp;
|
||||||
|
build(p - 1);
|
||||||
|
build(p + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(){
|
||||||
|
build(0);
|
||||||
|
if(!sum.empty()){
|
||||||
|
for(auto it = sum.begin(); it != sum.end(); ++it){
|
||||||
|
cout << it->second << " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
58
Algorithm/Recursion/UVa839 天平Not_so_Mobile.cpp
Normal file
58
Algorithm/Recursion/UVa839 天平Not_so_Mobile.cpp
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
#include <iostream>
|
||||||
|
//ǰ<><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ݹ<EFBFBD><DDB9><EFBFBD><EFBFBD>컨<EFBFBD><ECBBA8>
|
||||||
|
using namespace std;
|
||||||
|
struct mobile{
|
||||||
|
double lw, ll, rw, rl;
|
||||||
|
double weight;
|
||||||
|
mobile* left;
|
||||||
|
mobile* right;
|
||||||
|
|
||||||
|
mobile(double a, double b, double c, double d) : lw(a), ll(b), rw(c), rl(d), left(nullptr), right(nullptr) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
bool solve(mobile* &x){
|
||||||
|
double a, b, c, d;
|
||||||
|
bool b1 = true, b2 = true;
|
||||||
|
cin >> a >> b >> c >> d;
|
||||||
|
x = new mobile(a, b, c, d);
|
||||||
|
if(!x->lw) b1 = solve(x->left);
|
||||||
|
if(!x->rw) b2 = solve(x->right);
|
||||||
|
double leftWeight = x->left ? x->left->weight : x->lw;
|
||||||
|
double rightWeight = x->right ? x->right->weight : x->rw;
|
||||||
|
x->weight = leftWeight + rightWeight;
|
||||||
|
//<2F><>עreturn<72><6E><EFBFBD><EFBFBD><EFBFBD><EFBFBD>solveһ<65><D2BB><EFBFBD>Ǿ<EFBFBD><C7BE>Ƕ<EFBFBD><C7B6>εݹ<CEB5><DDB9>ˣ<EFBFBD><CBA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>solve<76><65>
|
||||||
|
return b1 && b2 && (leftWeight * x->ll == rightWeight * x->rl);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
ios::sync_with_stdio(false);
|
||||||
|
cin.tie(nullptr);
|
||||||
|
|
||||||
|
int n;
|
||||||
|
cin >> n;
|
||||||
|
string tmp;
|
||||||
|
getline(cin, tmp); // <20><>ȡ<EFBFBD><C8A1>һ<EFBFBD>к<EFBFBD><D0BA>Ļ<EFBFBD><C4BB><EFBFBD>
|
||||||
|
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
mobile* root = nullptr;
|
||||||
|
bool ok = solve(root);
|
||||||
|
cout << (ok ? "YES" : "NO") << "\n";
|
||||||
|
|
||||||
|
if (i != n - 1) cout << "\n"; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѯ֮<D1AF><D6AE><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
for(int i = 0; i < n - 1; i++){
|
||||||
|
cin >> a >> b >> c >> d;
|
||||||
|
mobile* tmp = new mobile(a, b, c, d);
|
||||||
|
if(a && !b){
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
<09><><EFBFBD>Dz<EFBFBD><C7B2>õģ<C3B5>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȼ<EFBFBD><C8BB>Ȼ<EFBFBD><C8BB><EFBFBD>γ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>
|
||||||
|
*/
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
BIN
Algorithm/Recursion/readme.md
Normal file
BIN
Algorithm/Recursion/readme.md
Normal file
Binary file not shown.
Reference in New Issue
Block a user