'commit'
This commit is contained in:
183
TangDou/AcWing/Dfs/1112.md
Normal file
183
TangDou/AcWing/Dfs/1112.md
Normal file
@@ -0,0 +1,183 @@
|
||||
## [$AcWing$ $1112$. 迷宫](https://www.acwing.com/problem/content/1114/)
|
||||
|
||||
### 一、题目描述
|
||||
一天$Extense$在森林里探险的时候不小心走入了一个迷宫,迷宫可以看成是由 $n∗n$ 的格点组成,每个格点只有$2$种状态,`.`和`#`,前者表示 **可以通行** 后者表示 **不能通行**。
|
||||
|
||||
同时当$Extense$处在某个格点时,他只能移动到东南西北(或者说**上下左右**)四个方向之一的相邻格点上,$Extense$想要从点$A$走到点$B$,问在不走出迷宫的情况下能不能办到。
|
||||
|
||||
如果起点或者终点有一个不能通行(为`#`),则看成无法办到。
|
||||
|
||||
**注意**:$A、B$不一定是两个不同的点。
|
||||
|
||||
**输入格式**
|
||||
第$1$行是测试数据的组数 $k$,后面跟着 $k$ 组输入。
|
||||
|
||||
每组测试数据的第1行是一个正整数 $n$,表示迷宫的规模是 $n∗n$ 的。
|
||||
|
||||
接下来是一个 $n∗n$ 的矩阵,矩阵中的元素为`.`或者`#`。
|
||||
|
||||
再接下来一行是 $4$ 个整数 $h_a,l_a,h_b,l_b$,描述 $A$ 处在第 $h_a$ 行, 第 $l_a$ 列,$B$ 处在第 $h_b$ 行, 第 $l_b$ 列。
|
||||
|
||||
注意到 $h_a,l_a,h_b,l_b$ 全部是从 $0$ 开始计数的。
|
||||
|
||||
**输出格式**
|
||||
$k$行,每行输出对应一个输入。
|
||||
|
||||
能办到则输出`YES`,否则输出`NO`。
|
||||
|
||||
**数据范围**
|
||||
$1≤n≤100$
|
||||
|
||||
**输入样例**:
|
||||
```cpp {.line-numbers}
|
||||
2
|
||||
3
|
||||
.##
|
||||
..#
|
||||
#..
|
||||
0 0 2 2
|
||||
5
|
||||
.....
|
||||
###.#
|
||||
..#..
|
||||
###..
|
||||
...#.
|
||||
0 0 4 0
|
||||
```
|
||||
|
||||
**输出样例**:
|
||||
```cpp {.line-numbers}
|
||||
YES
|
||||
NO
|
||||
```
|
||||
|
||||
### 二、$dfs$
|
||||
```cpp {.line-numbers}
|
||||
#include <bits/stdc++.h>
|
||||
|
||||
using namespace std;
|
||||
const int INF = 0x3f3f3f3f;
|
||||
// dfs只能求出来是否连通,第一次搜索到时并不能保证是最短距离
|
||||
// bfs也可以做,可以保证第一次到达时是最短距离
|
||||
// dfs好处是代码短,按时间排名,那么先AC的同学排名靠前
|
||||
// 用标记数组进行标记,每个位置只使用一次,性能N*N
|
||||
const int N = 110;
|
||||
int n;
|
||||
char g[N][N]; // 地图
|
||||
int xa, ya, xb, yb;
|
||||
int dx[] = {-1, 0, 1, 0};
|
||||
int dy[] = {0, 1, 0, -1};
|
||||
bool st[N][N]; // 是否走过
|
||||
bool flag;
|
||||
|
||||
void dfs(int x, int y) {
|
||||
if (x == xb && y == yb) {
|
||||
flag = true;
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int tx = x + dx[i], ty = y + dy[i];
|
||||
if (tx < 0 || tx == n || ty < 0 || ty == n) continue;
|
||||
if (st[tx][ty]) continue;
|
||||
if (g[tx][ty] == '#') continue;
|
||||
st[tx][ty] = true;
|
||||
dfs(tx, ty);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
int T;
|
||||
cin >> T;
|
||||
while (T--) {
|
||||
cin >> n;
|
||||
for (int i = 0; i < n; i++) cin >> g[i];
|
||||
cin >> xa >> ya >> xb >> yb;
|
||||
// 多组测试数组,每次初始化0
|
||||
memset(st, 0, sizeof st);
|
||||
flag = false;
|
||||
|
||||
// 这小坑坑挺多啊
|
||||
if (g[xa][ya] == '#' || g[xb][yb] == '#') {
|
||||
puts("NO");
|
||||
continue;
|
||||
}
|
||||
|
||||
st[xa][ya] = true;
|
||||
dfs(xa, ya);
|
||||
|
||||
if (flag)
|
||||
puts("YES");
|
||||
else
|
||||
puts("NO");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### 三、$bfs$
|
||||
```cpp {.line-numbers}
|
||||
#include <bits/stdc++.h>
|
||||
using namespace std;
|
||||
struct Node {
|
||||
int x;
|
||||
int y;
|
||||
int step;
|
||||
};
|
||||
const int N = 110;
|
||||
int dx[] = {-1, 0, 1, 0};
|
||||
int dy[] = {0, 1, 0, -1};
|
||||
char g[N][N];
|
||||
bool st[N][N];
|
||||
int n;
|
||||
int xa, ya, xb, yb; // 不能使用x1,y1这样的变量名,可能是万能头中有重复声明
|
||||
bool flag;
|
||||
void bfs() {
|
||||
flag = false;
|
||||
if (g[xa][ya] == '#') return;
|
||||
if (g[xb][yb] == '#') return;
|
||||
memset(st, 0, sizeof st);
|
||||
|
||||
if (xa == xb && ya == yb) {
|
||||
flag = true;
|
||||
return;
|
||||
}
|
||||
|
||||
queue<Node> q;
|
||||
q.push({xa, ya, 0});
|
||||
st[xa][ya] = true;
|
||||
|
||||
while (q.size()) {
|
||||
auto t = q.front();
|
||||
q.pop();
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int x = t.x + dx[i], y = t.y + dy[i];
|
||||
if (x < 0 || x >= n || y < 0 || y >= n) continue;
|
||||
if (st[x][y]) continue;
|
||||
if (g[x][y] == '#') continue;
|
||||
if (x == xb && y == yb) {
|
||||
flag = true;
|
||||
return;
|
||||
}
|
||||
q.push({x, y, t.step + 1});
|
||||
st[x][y] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
int main() {
|
||||
int T;
|
||||
cin >> T;
|
||||
while (T--) {
|
||||
cin >> n;
|
||||
for (int i = 0; i < n; i++) cin >> g[i];
|
||||
|
||||
cin >> xa >> ya >> xb >> yb;
|
||||
bfs();
|
||||
if (flag)
|
||||
cout << "YES" << endl;
|
||||
else
|
||||
cout << "NO" << endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
63
TangDou/AcWing/Dfs/1112_bfs_bool.cpp
Normal file
63
TangDou/AcWing/Dfs/1112_bfs_bool.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
#include <bits/stdc++.h>
|
||||
using namespace std;
|
||||
struct Node {
|
||||
int x;
|
||||
int y;
|
||||
int step;
|
||||
};
|
||||
const int N = 110;
|
||||
int dx[] = {-1, 0, 1, 0};
|
||||
int dy[] = {0, 1, 0, -1};
|
||||
char g[N][N];
|
||||
bool st[N][N];
|
||||
int n;
|
||||
int xa, ya, xb, yb; // 不能使用x1,y1这样的变量名,可能是万能头中有重复声明
|
||||
bool flag;
|
||||
void bfs() {
|
||||
flag = false;
|
||||
if (g[xa][ya] == '#') return;
|
||||
if (g[xb][yb] == '#') return;
|
||||
memset(st, 0, sizeof st);
|
||||
|
||||
if (xa == xb && ya == yb) {
|
||||
flag = true;
|
||||
return;
|
||||
}
|
||||
|
||||
queue<Node> q;
|
||||
q.push({xa, ya, 0});
|
||||
st[xa][ya] = true;
|
||||
|
||||
while (q.size()) {
|
||||
auto t = q.front();
|
||||
q.pop();
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int x = t.x + dx[i], y = t.y + dy[i];
|
||||
if (x < 0 || x >= n || y < 0 || y >= n) continue;
|
||||
if (st[x][y]) continue;
|
||||
if (g[x][y] == '#') continue;
|
||||
if (x == xb && y == yb) {
|
||||
flag = true;
|
||||
return;
|
||||
}
|
||||
q.push({x, y, t.step + 1});
|
||||
st[x][y] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
int main() {
|
||||
int T;
|
||||
cin >> T;
|
||||
while (T--) {
|
||||
cin >> n;
|
||||
for (int i = 0; i < n; i++) cin >> g[i];
|
||||
|
||||
cin >> xa >> ya >> xb >> yb;
|
||||
bfs();
|
||||
if (flag)
|
||||
cout << "YES" << endl;
|
||||
else
|
||||
cout << "NO" << endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
60
TangDou/AcWing/Dfs/1112_dfs_void_st.cpp
Normal file
60
TangDou/AcWing/Dfs/1112_dfs_void_st.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
#include <bits/stdc++.h>
|
||||
|
||||
using namespace std;
|
||||
const int INF = 0x3f3f3f3f;
|
||||
// dfs只能求出来是否连通,第一次搜索到时并不能保证是最短距离
|
||||
// bfs也可以做,可以保证第一次到达时是最短距离
|
||||
// dfs好处是代码短,按时间排名,那么先AC的同学排名靠前
|
||||
// 用标记数组进行标记,每个位置只使用一次,性能N*N
|
||||
const int N = 110;
|
||||
int n;
|
||||
char g[N][N]; // 地图
|
||||
int xa, ya, xb, yb;
|
||||
int dx[] = {-1, 0, 1, 0};
|
||||
int dy[] = {0, 1, 0, -1};
|
||||
bool st[N][N]; // 是否走过
|
||||
bool flag;
|
||||
|
||||
void dfs(int x, int y) {
|
||||
if (x == xb && y == yb) {
|
||||
flag = true;
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int tx = x + dx[i], ty = y + dy[i];
|
||||
if (tx < 0 || tx == n || ty < 0 || ty == n) continue;
|
||||
if (st[tx][ty]) continue;
|
||||
if (g[tx][ty] == '#') continue;
|
||||
st[tx][ty] = true;
|
||||
dfs(tx, ty);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
int T;
|
||||
cin >> T;
|
||||
while (T--) {
|
||||
cin >> n;
|
||||
for (int i = 0; i < n; i++) cin >> g[i];
|
||||
cin >> xa >> ya >> xb >> yb;
|
||||
// 多组测试数组,每次初始化0
|
||||
memset(st, 0, sizeof st);
|
||||
flag = false;
|
||||
|
||||
// 这小坑坑挺多啊
|
||||
if (g[xa][ya] == '#' || g[xb][yb] == '#') {
|
||||
puts("NO");
|
||||
continue;
|
||||
}
|
||||
|
||||
st[xa][ya] = true;
|
||||
dfs(xa, ya);
|
||||
|
||||
if (flag)
|
||||
puts("YES");
|
||||
else
|
||||
puts("NO");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
156
TangDou/AcWing/Dfs/1113.md
Normal file
156
TangDou/AcWing/Dfs/1113.md
Normal file
@@ -0,0 +1,156 @@
|
||||
## [$AcWing$ $1113$. 红与黑](https://www.acwing.com/problem/content/1115/)
|
||||
|
||||
### 一、题目描述
|
||||
有一间长方形的房子,地上铺了红色、黑色两种颜色的正方形瓷砖。
|
||||
|
||||
你站在其中一块 **黑色的瓷砖** 上,只能向相邻( **上下左右** 四个方向)的 **黑色** 瓷砖移动。
|
||||
|
||||
请写一个程序,计算你总共能够到达多少块黑色的瓷砖。
|
||||
|
||||
**输入格式**
|
||||
输入包括多个数据集合。
|
||||
|
||||
每个数据集合的第一行是两个整数 $W$ 和 $H$,分别表示 $x$ 方向和 $y$ 方向瓷砖的数量。
|
||||
|
||||
在接下来的 $H$ 行中,每行包括 $W$ 个字符。每个字符表示一块瓷砖的颜色,规则如下
|
||||
|
||||
1)‘.’:黑色的瓷砖;
|
||||
2)‘#’:红色的瓷砖;
|
||||
3)‘@’:黑色的瓷砖,并且你站在这块瓷砖上。该字符在每个数据集合中唯一出现一次。
|
||||
|
||||
当在一行中读入的是两个零时,表示输入结束。
|
||||
|
||||
**输出格式**
|
||||
对每个数据集合,分别输出一行,显示你从初始位置出发能到达的瓷砖数(记数时包括初始位置的瓷砖)。
|
||||
|
||||
**数据范围**
|
||||
$1≤W,H≤20$
|
||||
|
||||
**输入样例**:
|
||||
```cpp {.line-numbers}
|
||||
6 9
|
||||
....#.
|
||||
.....#
|
||||
......
|
||||
......
|
||||
......
|
||||
......
|
||||
......
|
||||
#@...#
|
||||
.#..#.
|
||||
0 0
|
||||
```
|
||||
|
||||
**输出样例**:
|
||||
```cpp {.line-numbers}
|
||||
45
|
||||
```
|
||||
|
||||
|
||||
### 二、$dfs$
|
||||
```cpp {.line-numbers}
|
||||
#include <bits/stdc++.h>
|
||||
using namespace std;
|
||||
|
||||
const int N = 25;
|
||||
// dfs 实现flood fill 算法
|
||||
|
||||
int n, m;
|
||||
char g[N][N];
|
||||
bool st[N][N];
|
||||
|
||||
int dx[] = {-1, 0, 1, 0};
|
||||
int dy[] = {0, 1, 0, -1};
|
||||
|
||||
int cnt;
|
||||
|
||||
void dfs(int x, int y) {
|
||||
// x,y贡献了1个结点数
|
||||
cnt++;
|
||||
st[x][y] = true;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int tx = x + dx[i], ty = y + dy[i];
|
||||
if (tx < 0 || tx >= n || ty < 0 || ty >= m) continue;
|
||||
if (g[tx][ty] != '.') continue;
|
||||
if (st[tx][ty]) continue;
|
||||
dfs(tx, ty);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
while (cin >> m >> n, n || m) { // 先输入列数,再输入行数,小坑
|
||||
// 多组测试数据
|
||||
memset(st, 0, sizeof st);
|
||||
cnt = 0;
|
||||
// 找起点
|
||||
int x, y;
|
||||
for (int i = 0; i < n; i++)
|
||||
for (int j = 0; j < m; j++) {
|
||||
cin >> g[i][j];
|
||||
if (g[i][j] == '@') x = i, y = j;
|
||||
}
|
||||
|
||||
dfs(x, y);
|
||||
printf("%d\n", cnt);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
### 三、$bfs$
|
||||
```cpp {.line-numbers}
|
||||
#include <bits/stdc++.h>
|
||||
using namespace std;
|
||||
|
||||
const int N = 30;
|
||||
struct Node {
|
||||
int x;
|
||||
int y;
|
||||
};
|
||||
|
||||
char g[N][N];
|
||||
int n, m;
|
||||
int dx[] = {0, 1, 0, -1};
|
||||
int dy[4] = {1, 0, -1, 0};
|
||||
bool st[N][N];
|
||||
int cnt;
|
||||
|
||||
void bfs(int x, int y) {
|
||||
queue<Node> q;
|
||||
q.push({x, y});
|
||||
|
||||
while (q.size()) {
|
||||
Node t = q.front();
|
||||
q.pop();
|
||||
cnt++;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int tx = t.x + dx[i], ty = t.y + dy[i];
|
||||
if (tx < 0 || tx >= n || ty < 0 || ty >= m) continue;
|
||||
if (st[tx][ty]) continue;
|
||||
if (g[tx][ty] != '.') continue;
|
||||
st[tx][ty] = true;
|
||||
q.push({tx, ty});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
while (cin >> m >> n, n || m) {
|
||||
memset(st, 0, sizeof st);
|
||||
cnt = 0;
|
||||
|
||||
int x, y;
|
||||
for (int i = 0; i < n; i++) {
|
||||
for (int j = 0; j < m; j++) {
|
||||
cin >> g[i][j];
|
||||
if (g[i][j] == '@') x = i, y = j;
|
||||
}
|
||||
}
|
||||
bfs(x, y);
|
||||
printf("%d\n", cnt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
52
TangDou/AcWing/Dfs/1113_bfs.cpp
Normal file
52
TangDou/AcWing/Dfs/1113_bfs.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
#include <bits/stdc++.h>
|
||||
using namespace std;
|
||||
|
||||
const int N = 30;
|
||||
struct Node {
|
||||
int x;
|
||||
int y;
|
||||
};
|
||||
|
||||
char g[N][N];
|
||||
int n, m;
|
||||
int dx[] = {0, 1, 0, -1};
|
||||
int dy[4] = {1, 0, -1, 0};
|
||||
bool st[N][N];
|
||||
int cnt;
|
||||
|
||||
void bfs(int x, int y) {
|
||||
queue<Node> q;
|
||||
q.push({x, y});
|
||||
|
||||
while (q.size()) {
|
||||
Node t = q.front();
|
||||
q.pop();
|
||||
cnt++;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int tx = t.x + dx[i], ty = t.y + dy[i];
|
||||
if (tx < 0 || tx >= n || ty < 0 || ty >= m) continue;
|
||||
if (st[tx][ty]) continue;
|
||||
if (g[tx][ty] != '.') continue;
|
||||
st[tx][ty] = true;
|
||||
q.push({tx, ty});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
while (cin >> m >> n, n || m) {
|
||||
memset(st, 0, sizeof st);
|
||||
cnt = 0;
|
||||
|
||||
int x, y;
|
||||
for (int i = 0; i < n; i++) {
|
||||
for (int j = 0; j < m; j++) {
|
||||
cin >> g[i][j];
|
||||
if (g[i][j] == '@') x = i, y = j;
|
||||
}
|
||||
}
|
||||
bfs(x, y);
|
||||
printf("%d\n", cnt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
48
TangDou/AcWing/Dfs/1113_dfs.cpp
Normal file
48
TangDou/AcWing/Dfs/1113_dfs.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
#include <bits/stdc++.h>
|
||||
using namespace std;
|
||||
|
||||
const int N = 25;
|
||||
// dfs 实现flood fill 算法
|
||||
|
||||
int n, m;
|
||||
char g[N][N];
|
||||
bool st[N][N];
|
||||
|
||||
int dx[] = {-1, 0, 1, 0};
|
||||
int dy[] = {0, 1, 0, -1};
|
||||
|
||||
int cnt;
|
||||
|
||||
void dfs(int x, int y) {
|
||||
// x,y贡献了1个结点数
|
||||
cnt++;
|
||||
st[x][y] = true;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int tx = x + dx[i], ty = y + dy[i];
|
||||
if (tx < 0 || tx >= n || ty < 0 || ty >= m) continue;
|
||||
if (g[tx][ty] != '.') continue;
|
||||
if (st[tx][ty]) continue;
|
||||
dfs(tx, ty);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
while (cin >> m >> n, n || m) { // 先输入列数,再输入行数,小坑
|
||||
// 多组测试数据
|
||||
memset(st, 0, sizeof st);
|
||||
cnt = 0;
|
||||
// 找起点
|
||||
int x, y;
|
||||
for (int i = 0; i < n; i++)
|
||||
for (int j = 0; j < m; j++) {
|
||||
cin >> g[i][j];
|
||||
if (g[i][j] == '@') x = i, y = j;
|
||||
}
|
||||
|
||||
dfs(x, y);
|
||||
printf("%d\n", cnt);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
32
TangDou/AcWing/Dfs/842.cpp
Normal file
32
TangDou/AcWing/Dfs/842.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#include <bits/stdc++.h>
|
||||
|
||||
using namespace std;
|
||||
const int N = 10;
|
||||
int n;
|
||||
int a[N], al;
|
||||
bool st[N];
|
||||
|
||||
void dfs(int u) {
|
||||
// 如果到达了终点
|
||||
if (u == n + 1) {
|
||||
for (int i = 0; i < n; i++)
|
||||
printf("%d ", a[i]);
|
||||
puts("");
|
||||
return;
|
||||
}
|
||||
for (int i = 1; i <= n; i++)
|
||||
if (!st[i]) {
|
||||
a[al++] = i;
|
||||
st[i] = true;
|
||||
dfs(u + 1);
|
||||
st[i] = false;
|
||||
al--;
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
cin >> n;
|
||||
// 开始
|
||||
dfs(1);
|
||||
return 0;
|
||||
}
|
||||
66
TangDou/AcWing/Dfs/842.md
Normal file
66
TangDou/AcWing/Dfs/842.md
Normal file
@@ -0,0 +1,66 @@
|
||||
##[$AcWing$ $842$. 排列数字](https://www.acwing.com/problem/content/description/844/)
|
||||
|
||||
### 一、题目描述
|
||||
给定一个整数 $n$,将数字 $1∼n$ 排成一排,将会有很多种排列方法。
|
||||
|
||||
现在,请你按照字典序将所有的排列方法输出。
|
||||
|
||||
**输入格式**
|
||||
共一行,包含一个整数 $n$。
|
||||
|
||||
**输出格式**
|
||||
按字典序输出所有排列方案,每个方案占一行。
|
||||
|
||||
|
||||
**数据范围**
|
||||
$1≤n≤7$
|
||||
|
||||
**输入样例:**
|
||||
```cpp {.line-numbers}
|
||||
3
|
||||
```
|
||||
**输出样例:**
|
||||
```cpp {.line-numbers}
|
||||
1 2 3
|
||||
1 3 2
|
||||
2 1 3
|
||||
2 3 1
|
||||
3 1 2
|
||||
3 2 1
|
||||
```
|
||||
|
||||
### 二、实现代码
|
||||
```cpp {.line-numbers}
|
||||
#include <bits/stdc++.h>
|
||||
|
||||
using namespace std;
|
||||
const int N = 10;
|
||||
int n;
|
||||
int a[N], al;
|
||||
bool st[N];
|
||||
|
||||
void dfs(int u) {
|
||||
// 如果到达了终点
|
||||
if (u == n + 1) {
|
||||
for (int i = 0; i < n; i++)
|
||||
printf("%d ", a[i]);
|
||||
puts("");
|
||||
return;
|
||||
}
|
||||
for (int i = 1; i <= n; i++)
|
||||
if (!st[i]) {
|
||||
a[al++] = i;
|
||||
st[i] = true;
|
||||
dfs(u + 1);
|
||||
st[i] = false;
|
||||
al--;
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
cin >> n;
|
||||
// 开始
|
||||
dfs(1);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
37
TangDou/AcWing/Dfs/843.cpp
Normal file
37
TangDou/AcWing/Dfs/843.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#include <bits/stdc++.h>
|
||||
using namespace std;
|
||||
const int N = 20;
|
||||
int path[N];
|
||||
int n;
|
||||
int b1[N], b2[N], b3[N];
|
||||
|
||||
void dfs(int u) {
|
||||
if (u == n + 1) { // 全部行都摆上皇后
|
||||
for (int i = 1; i <= n; i++) {
|
||||
for (int j = 1; j <= n; j++) {
|
||||
if (j == path[i])
|
||||
printf("Q");
|
||||
else
|
||||
printf(".");
|
||||
}
|
||||
puts("");
|
||||
}
|
||||
puts("");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 1; i <= n; i++) { // x行y列
|
||||
if (!b1[i] && !b2[u + i] && !b3[u - i + 8]) {
|
||||
path[u] = i;
|
||||
b1[i] = b2[u + i] = b3[u - i + 8] = 1;
|
||||
dfs(u + 1);
|
||||
b1[i] = b2[u + i] = b3[u - i + 8] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
cin >> n;
|
||||
dfs(1);
|
||||
return 0;
|
||||
}
|
||||
98
TangDou/AcWing/Dfs/843.md
Normal file
98
TangDou/AcWing/Dfs/843.md
Normal file
@@ -0,0 +1,98 @@
|
||||
##[$AcWing$ $843$. $n$-皇后问题](https://www.acwing.com/problem/content/description/845/)
|
||||
|
||||
### 一、题目描述
|
||||
$n$−皇后问题是指将 $n$ 个皇后放在 $n×n$ 的国际象棋棋盘上,使得皇后不能相互攻击到,即任意两个皇后都不能处于同一行、同一列或同一斜线上。
|
||||
|
||||
<center><img src='https://cdn.acwing.com/media/article/image/2019/06/08/19_860e00c489-1_597ec77c49-8-queens.png'></center>
|
||||
|
||||
|
||||
现在给定整数 $n$,请你输出所有的满足条件的棋子摆法。
|
||||
|
||||
**输入格式**
|
||||
共一行,包含整数 $n$。
|
||||
|
||||
**输出格式**
|
||||
每个解决方案占 $n$ 行,每行输出一个长度为 $n$ 的字符串,用来表示完整的棋盘状态。
|
||||
|
||||
其中 $.$ 表示某一个位置的方格状态为空,$Q$ 表示某一个位置的方格上摆着皇后。
|
||||
|
||||
每个方案输出完成后,输出一个空行。
|
||||
|
||||
注意:行末不能有多余空格。
|
||||
|
||||
输出方案的顺序任意,只要不重复且没有遗漏即可。
|
||||
|
||||
**数据范围**
|
||||
$1≤n≤9$
|
||||
**输入样例:**
|
||||
```cpp {.line-numbers}
|
||||
4
|
||||
```
|
||||
|
||||
**输出样例:**
|
||||
```cpp {.line-numbers}
|
||||
.Q..
|
||||
...Q
|
||||
Q...
|
||||
..Q.
|
||||
|
||||
..Q.
|
||||
Q...
|
||||
...Q
|
||||
.Q..
|
||||
```
|
||||
|
||||
### 二、题目分析
|
||||
|
||||
<img src='https://cdn.acwing.com/media/article/image/2021/02/07/64630_957f747469-QQ%E6%88%AA%E5%9B%BE20210207131455.png'>
|
||||
|
||||
### 三、实现代码
|
||||
```cpp {.line-numbers}
|
||||
#include <bits/stdc++.h>
|
||||
|
||||
using namespace std;
|
||||
const int N = 1e5 + 10; // Q:为什么这里是110,还是最大是9吗?这是因为在下面的数组使用中,采用了+8的偏移策略,需要大一点,只要开不死,就往死里开!
|
||||
int path[N];
|
||||
int n;
|
||||
int b1[N], b2[N], b3[N];
|
||||
|
||||
void dfs(int u) {
|
||||
if (u == n + 1) { // 全部行都摆上皇后
|
||||
for (int i = 1; i <= n; i++) {
|
||||
for (int j = 1; j <= n; j++) {
|
||||
if (j == path[i])
|
||||
printf("Q");
|
||||
else
|
||||
printf(".");
|
||||
}
|
||||
puts("");
|
||||
}
|
||||
puts("");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 1; i <= n; i++) { // x行y列
|
||||
/*
|
||||
1、因为x上按行一行一行来的,所以不用考虑行的冲突,只需要考虑列、正对角线,反对角线三个方向。
|
||||
2、b2[x+i] 因为同一正角线的位置,行+列是相等的,如果我们设置了 行+列使用过了,
|
||||
那么,其它再检查到同一对角线时,就会发现行+列已使用过
|
||||
3、b3[x - i + 8] 因为同一反对角线的位置,行-列是相等的,但可能行>列,也可能列>行,
|
||||
这要看它是最长对角线的右上方还是左下方,右上方x>y,左下方x<y 为了防止出现负数数组下标,
|
||||
所以,采用了加一个偏移量的办法,这样,不管是大于还是小于,都规划到一个下标大于零的位置上。
|
||||
4、这里不能使用abs,因为 abs(x-y)与abs(y-x)不是一条反对角线!!!
|
||||
为什么是8?就是因为n的范围是9,b3数组下标不越界即可!即1-9+8=0*/
|
||||
if (!b1[i] && !b2[u + i] && !b3[u - i + 8]) {
|
||||
path[u] = i;
|
||||
b1[i] = b2[u + i] = b3[u - i + 8] = 1;
|
||||
dfs(u + 1);
|
||||
b1[i] = b2[u + i] = b3[u - i + 8] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
cin >> n;
|
||||
dfs(1);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
39
TangDou/AcWing/Dfs/CF484E.md
Normal file
39
TangDou/AcWing/Dfs/CF484E.md
Normal file
@@ -0,0 +1,39 @@
|
||||
https://codeforces.com/problemset/problem/484/E?f0a28=1
|
||||
https://www.luogu.com.cn/problem/CF484E
|
||||
|
||||
Q:本题为什么没有使用离散化?主席树到底需不需要离散化??
|
||||
|
||||
### 一、题目描述
|
||||
给我们一组数,并给出$m$个询问,每个询问包括$l,r,w$三个数,询问我们在$l$到$r$这个区间内连续取$w$个数,使这$w$个数中的**最小值**尽可能的**大**,输出这个**最大的最小值**。
|
||||
|
||||
### 二、解题思路
|
||||
首先我们先假设在当前的询问下$x$这个数可以成为连续$w$个数中的最小值($x$一定为某个数的值),然后把数列中大于等于$x$的数标为$1$,小于$x$的数标为$0$,那么如果我们求出这个$01$串中最长的$1$串长度为$s$,且$s>=w$的话,$x$就可以拿去更新当前答案,然后我们就枚举比$x$大的值看是否符合条件,当然这个枚举过程用二分实现。
|
||||
|
||||
用线段树求一串数中最长的$1$串,应该都做过。所以问题就变成了我们如何来建立这个$01$串,很显然,我们不可能去构造$n$棵线段树。假设有两个数$x,y$且$x>y$那么很显然$y$的$01$串是$x$的$01$串的基础上多添加了几个$1$,所以我们可以用可持续化线段树来维护当前$01$串下的最长$1$串的长度。
|
||||
|
||||
|
||||
### 二、个人感悟过程
|
||||
|
||||
#### 1、主席树为什么要记录$[l,r]$,其它题的主席树也记录了左右边界吗?
|
||||
答: 区间内第$k$小的数,也是记录了$l,r$,看来记录$l,r$是通用办法。
|
||||
|
||||
#### 2、在左前缀,右后缀,连续最大值这样的问题中,左右边界的长度都很关键,是直接记录len,还是通过记录l,r,计算出len?
|
||||
答: 既然主席树中都需要记录$l,r$,那么
|
||||
```c++
|
||||
int len(){
|
||||
return r-l+1;
|
||||
}
|
||||
```
|
||||
就是标配了。
|
||||
|
||||
#### 3、$0$号版本似乎就是个架子,没有真正的内容。真正的内容都是一个一个,通过$insert$装载进来,生成一个个版本的。
|
||||
答:事实上是这样的,但这个动作是标配,不能省略。
|
||||
|
||||
#### 4、 insert和query的参数
|
||||
p参数都表示以此版本的线段树,是以p号节点为根节点的。
|
||||
|
||||
#### 5、insert和query的返回值
|
||||
insert:返回的是新增加一个数值后,新创建的版本对应的根节点编号q
|
||||
query:返回的是一个查询拼接后的结构体,以便读取mx,lx,rx等信息。
|
||||
|
||||
|
||||
42
TangDou/AcWing/Dfs/MaZouRi.cpp
Normal file
42
TangDou/AcWing/Dfs/MaZouRi.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
#include <bits/stdc++.h>
|
||||
using namespace std;
|
||||
const int N = 10;
|
||||
int n, m;
|
||||
int res;
|
||||
int dx[] = {2, 2, 1, -1, -2, -2, 1, -1};
|
||||
int dy[] = {1, -1, 2, 2, 1, -1, -2, -2}; // 进行移动
|
||||
bool st[N][N]; // 判断该数是否被标记过
|
||||
|
||||
// 马走日的回溯法实现
|
||||
void dfs(int x, int y, int cnt) {
|
||||
if (cnt == n * m) {
|
||||
res++;
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
int tx = x + dx[i], ty = y + dy[i];
|
||||
if (tx < 0 || ty < 0 || tx >= n || ty >= m) continue;
|
||||
if (st[tx][ty]) continue;
|
||||
|
||||
st[tx][ty] = 1;
|
||||
dfs(tx, ty, cnt + 1);
|
||||
st[tx][ty] = 0;
|
||||
}
|
||||
}
|
||||
int main() {
|
||||
int T;
|
||||
cin >> T;
|
||||
while (T--) { // 多组测试数据
|
||||
res = 0;
|
||||
memset(st, 0, sizeof st);
|
||||
|
||||
int x, y; // 初始位置坐标
|
||||
cin >> n >> m >> x >> y;
|
||||
|
||||
st[x][y] = 1; // 标记起点
|
||||
dfs(x, y, 1);
|
||||
st[x][y] = 0; // 其实,出发点是否回溯无所谓,不会对其它人造成影响,而且,下一轮开始时有清空操作
|
||||
cout << res << endl;
|
||||
}
|
||||
}
|
||||
39
TangDou/AcWing/Dfs/TD.cpp
Normal file
39
TangDou/AcWing/Dfs/TD.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
#include <bits/stdc++.h>
|
||||
|
||||
using namespace std;
|
||||
const int N = 10;
|
||||
int g[N][N];
|
||||
int st[N][N];
|
||||
int dx[] = {-1, 0, 1, 0};
|
||||
int dy[] = {0, 1, 0, -1};
|
||||
int n, m, T;
|
||||
int cnt;
|
||||
int sx, sy, fx, fy;
|
||||
|
||||
void dfs(int x, int y) {
|
||||
if (x == fx && y == fy) {
|
||||
cnt++;
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int tx = x + dx[i], ty = y + dy[i];
|
||||
if (tx <= 0 || ty <= 0 || tx > n || ty > m) continue;
|
||||
if (st[tx][ty]) continue;
|
||||
st[tx][ty] = 1;
|
||||
dfs(tx, ty);
|
||||
st[tx][ty] = 0;
|
||||
}
|
||||
}
|
||||
int main() {
|
||||
cin >> n >> m >> T;
|
||||
cin >> sx >> sy >> fx >> fy;
|
||||
while (T--) {
|
||||
int x, y;
|
||||
cin >> x >> y;
|
||||
st[x][y] = 1;
|
||||
}
|
||||
st[sx][sy] = 1;
|
||||
dfs(sx, sy);
|
||||
cout << cnt << endl;
|
||||
return 0;
|
||||
}
|
||||
39
TangDou/AcWing/Dfs/ZouMiGong.cpp
Normal file
39
TangDou/AcWing/Dfs/ZouMiGong.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
#include <bits/stdc++.h>
|
||||
|
||||
using namespace std;
|
||||
const int N = 10;
|
||||
int g[N][N];
|
||||
int st[N][N];
|
||||
int dx[] = {-1, 0, 1, 0}; // 上右下左
|
||||
int dy[] = {0, 1, 0, -1}; // 上右下左
|
||||
int n, m, T;
|
||||
int cnt;
|
||||
int sx, sy, fx, fy;
|
||||
|
||||
void dfs(int x, int y) {
|
||||
if (x == fx && y == fy) {
|
||||
cnt++;
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int tx = x + dx[i], ty = y + dy[i];
|
||||
if (tx <= 0 || ty <= 0 || tx > n || ty > m) continue;
|
||||
if (st[tx][ty]) continue;
|
||||
st[tx][ty] = 1;
|
||||
dfs(tx, ty);
|
||||
st[tx][ty] = 0;
|
||||
}
|
||||
}
|
||||
int main() {
|
||||
cin >> n >> m >> T;
|
||||
cin >> sx >> sy >> fx >> fy;
|
||||
while (T--) {
|
||||
int x, y;
|
||||
cin >> x >> y;
|
||||
st[x][y] = 1; // 标障碍点
|
||||
}
|
||||
st[sx][sy] = 1;
|
||||
dfs(sx, sy);
|
||||
cout << cnt << endl;
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user