A - 组合的输出
#include <cstdio>#include <cstring>using namespace std;const int MAXN = 25 + 1;int n, r;int a[MAXN]; //数组a保存在“棋盘”上的"棋子"void dfs(int k) {for (int i = a[k - 1] + 1; i <= n; i++) {a[k] = i;if (k == r) {for (int j = 1; j <= r; j++) printf("%3d", a[j]);printf("\n");}else {dfs(k + 1);}}}int main() {while (~scanf("%d%d", &n, &r)) {memset(a, 0, sizeof(a));dfs(1);}return 0;}
B - 自然数拆分
#include <iostream>#include <cstring>using namespace std;const int MAXN = 30;int n,sum = 0;int a[MAXN];void dfs(int k) {for (int i = a[k-1]; i <= n; i++) { //每次从上一个填入的数字开始if (i == n) continue;sum -= a[k]; //虽然我用了回溯,但是这种用法不是很优雅a[k] = i;sum += a[k];if (sum == n) {cout << n << '=';for (int i = 1; i < k; i++) {cout << a[i] << '+';}cout << a[k] << endl;sum -= i;a[k] = 0;}else if (sum < n) {dfs(k + 1);}else {sum = sum - i;a[k] = 0;}}}int main() {cin >> n;memset(a, 0, sizeof(a));sum = 0;a[0] = 1; //注意边界dfs(1);return 0;}
优雅的改进版
void dfs(int k) {for (int i = a[k-1]; i <= n - sum; i++) { //n-sum避免 sum > n的情况,该情况要回溯“两次”if (i == n) continue;a[k] = i;sum += a[k];if (sum == n) {cout << n << '=';for (int i = 1; i < k; i++) {cout << a[i] << '+';}cout << a[k] << endl;}else {dfs(k + 1);}sum -= i;}}
C - LETTERS(这起得什么无意义的名字)
#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int MAXN = 100;int m, n;string s;char a[MAXN][21] = {0};bool vis[MAXN][21] = { 0 };int ans = 0;void dfs(int i, int j) {if (vis[i][j] == 1 || i < 1 || i > m || j < 1 || j > n) return; //出界或是已经访问过char c = a[i][j];if (s.find(c) != EOF) return; //每种字符只能访问一次vis[i][j] = 1;s += c;/*cout << s << endl;*/if (s.size() > ans) { ans = s.size(); /*cout << s << ' ' << ans << endl;*/ }int pos = s.size() - 1;dfs(i - 1, j);dfs(i + 1, j);dfs(i, j - 1);dfs(i, j + 1);s.erase(pos); //回溯,把/**/中的输出添加上可以发现有回溯和没有回溯的区别vis[i][j] = 0;return;}int main() {while (~scanf_s("%d%d", &m, &n)) {s.clear();ans = 0;memset(a, 0, sizeof(a));memset(vis, 0, sizeof(vis));for (int i = 1; i <= m; i++) {for (int j = 1; j <= n; j++) {cin >> a[i][j];}}dfs(1, 1);cout << ans << endl;}return 0;}
D-n皇后问题
#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int MAXN = 21;int n;int ans = 0;int a[MAXN] = { 0 };void showMap() {for (int i = 1; i <= n; i++) {for (int j = 1; j <= n; j++) {if (j == a[i]) cout << '1' << ' ';else cout << '0' << ' ';}cout << endl;}cout << endl;}bool check(int x, int y) {for (int i = 1; i < x; i++) {if (a[i] == y) return false;if (i + a[i] == x + y) return false;if (i - a[i] == x - y) return false;}return true;}void dfs(int row) {if (row == n + 1) {showMap();ans++;return;}for (int i = 1; i <= n; i++) {if (check(row, i)) {a[row] = i;dfs(row + 1);a[row] = 0; //回溯}}}int main() {cin >> n;dfs(1);cout << ans;return 0;}
八皇后(改)
#include <iostream>#include <algorithm>#include <cstring>using namespace std;const int n = 8;int ans = 0, pos = 1;int a[n + 1] = { 0 };int order[93] = { 0 };void func() {for (int i = 1; i <= 8; i++) {cout << a[i];}cout << endl;}bool check(int x, int y) {for (int i = 1; i < x; i++) {if (a[i] == y) return false;if (i + a[i] == x + y) return false;if (i - a[i] == x - y) return false;}return true;}void dfs(int row) {if (row == n + 1) {ans++;if (ans == order[pos]) {pos++;func();}return;}for (int i = 1; i <= n; i++) {if (check(row, i)) {a[row] = i;dfs(row + 1);a[row] = 0; //回溯}}}int main() {int num;cin >> num;for (int i = 1; i <= num; i++) {cin >> order[i];}sort(order + 1, order + 1 + num);dfs(1);return 0;}
F - 迷宫(一)
#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int MAXN = 21;char a[MAXN][11] = { 0 };bool vis[MAXN][11] = { 0 };int n, m, s1, s2, g1, g2;int flag = 0;void dfs(int x, int y) {if (x == g1 && y == g2) { flag = 1; return; }if (vis[x][y] == 1 || x < 1 || x > n || y < 1 || y > m) return;vis[x][y] = 1;dfs(x - 1, y);dfs(x + 1, y);dfs(x, y - 1);dfs(x, y + 1);vis[x][y] = 0; //回溯}int main() {cin >> n >> m;for (int i = 1; i <= n; i++) {for (int j = 1; j <= m; j++) {cin >> a[i][j];if (a[i][j] == 'S') { s1 = i; s2 = j; } //保存入口坐标if (a[i][j] == 'T') { g1 = i; g2 = j; } //保存出口坐标if (a[i][j] == '*') vis[i][j] = 1; //墙壁不可通过}}dfs(s1, s2);if (flag) cout << "yes";else cout << "no";return 0;}
G - 迷宫(二)
#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int MAXN = 21;char a[MAXN][11] = { 0 };bool vis[MAXN][11] = { 0 };int n, m, s1, s2, g1, g2;int ans = -1,cnt = 0;void dfs(int x, int y) {if (x == g1 && y == g2) {ans++;if (cnt == 0) cnt = ans;else cnt = cnt < ans ? cnt : ans;ans--; //回溯return;}if (vis[x][y] == 1 || x < 1 || x > n || y < 1 || y > m) return;vis[x][y] = 1;ans++;dfs(x - 1, y);dfs(x + 1, y);dfs(x, y - 1);dfs(x, y + 1);vis[x][y] = 0; //回溯ans--;}int main() {cin >> n >> m;for (int i = 1; i <= n; i++) {for (int j = 1; j <= m; j++) {cin >> a[i][j];if (a[i][j] == 'S') { s1 = i; s2 = j; } //保存入口坐标if (a[i][j] == 'T') { g1 = i; g2 = j; } //保存出口坐标if (a[i][j] == '*') vis[i][j] = 1; //墙壁不可通过}}dfs(s1, s2);if (cnt) cout << cnt;else cout << "-1";return 0;}
H - 迷宫(三)
#include <iostream>using namespace std;const int MAXN = 31;bool goal[MAXN][16] = { 0 };bool vis[MAXN][16] = { 0 };int n, m;int ans = -1,cnt = 0;void dfs(int x, int y) {if (goal[x][y] == 1) { //到达终点ans++;if (cnt == 0) cnt = ans;else cnt = cnt < ans ? cnt : ans;ans--; //回溯return;}if (vis[x][y] == 1 || x < 1 || x > n || y < 1 || y > m) return;vis[x][y] = 1;ans++;dfs(x - 1, y);dfs(x + 1, y);dfs(x, y - 1);dfs(x, y + 1);vis[x][y] = 0; //回溯ans--;}int main() {char ch;cin >> n >> m;int x, y;for (int i = 1; i <= n; i++) {for (int j = 1; j <= m; j++) {cin >> ch;if (ch == '#') vis[i][j] = 1; //墙壁不可通过else if ((i == 1 || i == n || j == 1 || j == m) && ch == '.') { goal[i][j] = 1; } //保存终点坐标if (ch == '@') { x = i; y = j; } //保存起点坐标}}dfs(x, y);if (cnt) cout << cnt;else cout << "-1";return 0;}
I - 棋盘问题(递归理解重点题)
#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int MAXN = 9;int a[MAXN] = { 0 };char map[MAXN][MAXN] = { 0 };int n, k, ans;int num = 0;bool check(int x, int y) {if (map[x][y] == '.') return false;for (int i = 1; i < x; i++) {if (a[i] == y) return false;}return true;}void dfs(int row) {if (num == k) { ans++; return; } //值得注意的点if (row == n + 1) return;for (int i = 1; i <= n; i++) {if (check(row, i)) {a[row] = i;num++;dfs(row + 1);a[row] = 0;num--;}}dfs(row + 1); //本题的精髓:}int main() {while (~scanf_s("%d%d", &n, &k)) {if (n == -1 && k == -1) break;/*init*/memset(a, 0, sizeof(a));memset(map, 0, sizeof(map));ans = 0;num = 0;/*input*/for (int i = 1; i <= n; i++) {for (int j = 1; j <= n; j++) {cin >> map[i][j];}}/*dfs*/dfs(1);/*output*/cout << "ans = " << ans;}return 0;}
L - 马走日
我的答案是正确答案的8倍,以下为修改版 ```cpp
include
include
include
using namespace std; const int MAXN = 6; int m, n; bool vis[MAXN][MAXN] = { 0 }; int step = 0, ans = 0; int dir1[8] = { 1,1,-1,-1,2,2,-2,-2 }; int dir2[8] = { 2,-2,2,-2,1,-1,1,-1 }; bool checkSteps(int x, int y) //判断每次搜索的方向是否合法 { if (vis[x][y] == true) //判断是否被走过了
return false;
if (x >= n || x < 0 || y >= m || y < 0) //判断是否越界
return false;
return true; } void dfs(int x,int y) { if (step == n * m - 1) { ans++; return; } for (int i = 0; i < 8; i++) {
if (!checkSteps(x + dir1[i], y + dir2[i])) continue;step++;vis[x][y] = 1;dfs(x + dir1[i], y + dir2[i]);step--; //回溯vis[x][y] = 0;
} }
int main() { int t; cin >> t; for (int i = 1; i <= t; i++) { int x, y; cin >> n >> m >> x >> y; /init/ memset(vis, 0, sizeof(vis)); ans = 0; step = 0; /dfs/ dfs(x, y); cout << ans << endl; } return 0; } ```
