A - 组合的输出

  1. #include <cstdio>
  2. #include <cstring>
  3. using namespace std;
  4. const int MAXN = 25 + 1;
  5. int n, r;
  6. int a[MAXN]; //数组a保存在“棋盘”上的"棋子"
  7. void dfs(int k) {
  8. for (int i = a[k - 1] + 1; i <= n; i++) {
  9. a[k] = i;
  10. if (k == r) {
  11. for (int j = 1; j <= r; j++) printf("%3d", a[j]);
  12. printf("\n");
  13. }
  14. else {
  15. dfs(k + 1);
  16. }
  17. }
  18. }
  19. int main() {
  20. while (~scanf("%d%d", &n, &r)) {
  21. memset(a, 0, sizeof(a));
  22. dfs(1);
  23. }
  24. return 0;
  25. }

B - 自然数拆分

  1. #include <iostream>
  2. #include <cstring>
  3. using namespace std;
  4. const int MAXN = 30;
  5. int n,sum = 0;
  6. int a[MAXN];
  7. void dfs(int k) {
  8. for (int i = a[k-1]; i <= n; i++) { //每次从上一个填入的数字开始
  9. if (i == n) continue;
  10. sum -= a[k]; //虽然我用了回溯,但是这种用法不是很优雅
  11. a[k] = i;
  12. sum += a[k];
  13. if (sum == n) {
  14. cout << n << '=';
  15. for (int i = 1; i < k; i++) {
  16. cout << a[i] << '+';
  17. }
  18. cout << a[k] << endl;
  19. sum -= i;
  20. a[k] = 0;
  21. }
  22. else if (sum < n) {
  23. dfs(k + 1);
  24. }
  25. else {
  26. sum = sum - i;
  27. a[k] = 0;
  28. }
  29. }
  30. }
  31. int main() {
  32. cin >> n;
  33. memset(a, 0, sizeof(a));
  34. sum = 0;
  35. a[0] = 1; //注意边界
  36. dfs(1);
  37. return 0;
  38. }

优雅的改进版

  1. void dfs(int k) {
  2. for (int i = a[k-1]; i <= n - sum; i++) { //n-sum避免 sum > n的情况,该情况要回溯“两次”
  3. if (i == n) continue;
  4. a[k] = i;
  5. sum += a[k];
  6. if (sum == n) {
  7. cout << n << '=';
  8. for (int i = 1; i < k; i++) {
  9. cout << a[i] << '+';
  10. }
  11. cout << a[k] << endl;
  12. }
  13. else {
  14. dfs(k + 1);
  15. }
  16. sum -= i;
  17. }
  18. }

C - LETTERS(这起得什么无意义的名字)

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. using namespace std;
  5. const int MAXN = 100;
  6. int m, n;
  7. string s;
  8. char a[MAXN][21] = {0};
  9. bool vis[MAXN][21] = { 0 };
  10. int ans = 0;
  11. void dfs(int i, int j) {
  12. if (vis[i][j] == 1 || i < 1 || i > m || j < 1 || j > n) return; //出界或是已经访问过
  13. char c = a[i][j];
  14. if (s.find(c) != EOF) return; //每种字符只能访问一次
  15. vis[i][j] = 1;
  16. s += c;
  17. /*cout << s << endl;*/
  18. if (s.size() > ans) { ans = s.size(); /*cout << s << ' ' << ans << endl;*/ }
  19. int pos = s.size() - 1;
  20. dfs(i - 1, j);
  21. dfs(i + 1, j);
  22. dfs(i, j - 1);
  23. dfs(i, j + 1);
  24. s.erase(pos); //回溯,把/**/中的输出添加上可以发现有回溯和没有回溯的区别
  25. vis[i][j] = 0;
  26. return;
  27. }
  28. int main() {
  29. while (~scanf_s("%d%d", &m, &n)) {
  30. s.clear();
  31. ans = 0;
  32. memset(a, 0, sizeof(a));
  33. memset(vis, 0, sizeof(vis));
  34. for (int i = 1; i <= m; i++) {
  35. for (int j = 1; j <= n; j++) {
  36. cin >> a[i][j];
  37. }
  38. }
  39. dfs(1, 1);
  40. cout << ans << endl;
  41. }
  42. return 0;
  43. }

D-n皇后问题

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. using namespace std;
  5. const int MAXN = 21;
  6. int n;
  7. int ans = 0;
  8. int a[MAXN] = { 0 };
  9. void showMap() {
  10. for (int i = 1; i <= n; i++) {
  11. for (int j = 1; j <= n; j++) {
  12. if (j == a[i]) cout << '1' << ' ';
  13. else cout << '0' << ' ';
  14. }
  15. cout << endl;
  16. }
  17. cout << endl;
  18. }
  19. bool check(int x, int y) {
  20. for (int i = 1; i < x; i++) {
  21. if (a[i] == y) return false;
  22. if (i + a[i] == x + y) return false;
  23. if (i - a[i] == x - y) return false;
  24. }
  25. return true;
  26. }
  27. void dfs(int row) {
  28. if (row == n + 1) {
  29. showMap();
  30. ans++;
  31. return;
  32. }
  33. for (int i = 1; i <= n; i++) {
  34. if (check(row, i)) {
  35. a[row] = i;
  36. dfs(row + 1);
  37. a[row] = 0; //回溯
  38. }
  39. }
  40. }
  41. int main() {
  42. cin >> n;
  43. dfs(1);
  44. cout << ans;
  45. return 0;
  46. }

八皇后(改)

  1. #include <iostream>
  2. #include <algorithm>
  3. #include <cstring>
  4. using namespace std;
  5. const int n = 8;
  6. int ans = 0, pos = 1;
  7. int a[n + 1] = { 0 };
  8. int order[93] = { 0 };
  9. void func() {
  10. for (int i = 1; i <= 8; i++) {
  11. cout << a[i];
  12. }
  13. cout << endl;
  14. }
  15. bool check(int x, int y) {
  16. for (int i = 1; i < x; i++) {
  17. if (a[i] == y) return false;
  18. if (i + a[i] == x + y) return false;
  19. if (i - a[i] == x - y) return false;
  20. }
  21. return true;
  22. }
  23. void dfs(int row) {
  24. if (row == n + 1) {
  25. ans++;
  26. if (ans == order[pos]) {
  27. pos++;
  28. func();
  29. }
  30. return;
  31. }
  32. for (int i = 1; i <= n; i++) {
  33. if (check(row, i)) {
  34. a[row] = i;
  35. dfs(row + 1);
  36. a[row] = 0; //回溯
  37. }
  38. }
  39. }
  40. int main() {
  41. int num;
  42. cin >> num;
  43. for (int i = 1; i <= num; i++) {
  44. cin >> order[i];
  45. }
  46. sort(order + 1, order + 1 + num);
  47. dfs(1);
  48. return 0;
  49. }

F - 迷宫(一)

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. using namespace std;
  5. const int MAXN = 21;
  6. char a[MAXN][11] = { 0 };
  7. bool vis[MAXN][11] = { 0 };
  8. int n, m, s1, s2, g1, g2;
  9. int flag = 0;
  10. void dfs(int x, int y) {
  11. if (x == g1 && y == g2) { flag = 1; return; }
  12. if (vis[x][y] == 1 || x < 1 || x > n || y < 1 || y > m) return;
  13. vis[x][y] = 1;
  14. dfs(x - 1, y);
  15. dfs(x + 1, y);
  16. dfs(x, y - 1);
  17. dfs(x, y + 1);
  18. vis[x][y] = 0; //回溯
  19. }
  20. int main() {
  21. cin >> n >> m;
  22. for (int i = 1; i <= n; i++) {
  23. for (int j = 1; j <= m; j++) {
  24. cin >> a[i][j];
  25. if (a[i][j] == 'S') { s1 = i; s2 = j; } //保存入口坐标
  26. if (a[i][j] == 'T') { g1 = i; g2 = j; } //保存出口坐标
  27. if (a[i][j] == '*') vis[i][j] = 1; //墙壁不可通过
  28. }
  29. }
  30. dfs(s1, s2);
  31. if (flag) cout << "yes";
  32. else cout << "no";
  33. return 0;
  34. }

G - 迷宫(二)

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. using namespace std;
  5. const int MAXN = 21;
  6. char a[MAXN][11] = { 0 };
  7. bool vis[MAXN][11] = { 0 };
  8. int n, m, s1, s2, g1, g2;
  9. int ans = -1,cnt = 0;
  10. void dfs(int x, int y) {
  11. if (x == g1 && y == g2) {
  12. ans++;
  13. if (cnt == 0) cnt = ans;
  14. else cnt = cnt < ans ? cnt : ans;
  15. ans--; //回溯
  16. return;
  17. }
  18. if (vis[x][y] == 1 || x < 1 || x > n || y < 1 || y > m) return;
  19. vis[x][y] = 1;
  20. ans++;
  21. dfs(x - 1, y);
  22. dfs(x + 1, y);
  23. dfs(x, y - 1);
  24. dfs(x, y + 1);
  25. vis[x][y] = 0; //回溯
  26. ans--;
  27. }
  28. int main() {
  29. cin >> n >> m;
  30. for (int i = 1; i <= n; i++) {
  31. for (int j = 1; j <= m; j++) {
  32. cin >> a[i][j];
  33. if (a[i][j] == 'S') { s1 = i; s2 = j; } //保存入口坐标
  34. if (a[i][j] == 'T') { g1 = i; g2 = j; } //保存出口坐标
  35. if (a[i][j] == '*') vis[i][j] = 1; //墙壁不可通过
  36. }
  37. }
  38. dfs(s1, s2);
  39. if (cnt) cout << cnt;
  40. else cout << "-1";
  41. return 0;
  42. }

H - 迷宫(三)

  1. #include <iostream>
  2. using namespace std;
  3. const int MAXN = 31;
  4. bool goal[MAXN][16] = { 0 };
  5. bool vis[MAXN][16] = { 0 };
  6. int n, m;
  7. int ans = -1,cnt = 0;
  8. void dfs(int x, int y) {
  9. if (goal[x][y] == 1) { //到达终点
  10. ans++;
  11. if (cnt == 0) cnt = ans;
  12. else cnt = cnt < ans ? cnt : ans;
  13. ans--; //回溯
  14. return;
  15. }
  16. if (vis[x][y] == 1 || x < 1 || x > n || y < 1 || y > m) return;
  17. vis[x][y] = 1;
  18. ans++;
  19. dfs(x - 1, y);
  20. dfs(x + 1, y);
  21. dfs(x, y - 1);
  22. dfs(x, y + 1);
  23. vis[x][y] = 0; //回溯
  24. ans--;
  25. }
  26. int main() {
  27. char ch;
  28. cin >> n >> m;
  29. int x, y;
  30. for (int i = 1; i <= n; i++) {
  31. for (int j = 1; j <= m; j++) {
  32. cin >> ch;
  33. if (ch == '#') vis[i][j] = 1; //墙壁不可通过
  34. else if ((i == 1 || i == n || j == 1 || j == m) && ch == '.') { goal[i][j] = 1; } //保存终点坐标
  35. if (ch == '@') { x = i; y = j; } //保存起点坐标
  36. }
  37. }
  38. dfs(x, y);
  39. if (cnt) cout << cnt;
  40. else cout << "-1";
  41. return 0;
  42. }

I - 棋盘问题(递归理解重点题)

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. using namespace std;
  5. const int MAXN = 9;
  6. int a[MAXN] = { 0 };
  7. char map[MAXN][MAXN] = { 0 };
  8. int n, k, ans;
  9. int num = 0;
  10. bool check(int x, int y) {
  11. if (map[x][y] == '.') return false;
  12. for (int i = 1; i < x; i++) {
  13. if (a[i] == y) return false;
  14. }
  15. return true;
  16. }
  17. void dfs(int row) {
  18. if (num == k) { ans++; return; } //值得注意的点
  19. if (row == n + 1) return;
  20. for (int i = 1; i <= n; i++) {
  21. if (check(row, i)) {
  22. a[row] = i;
  23. num++;
  24. dfs(row + 1);
  25. a[row] = 0;
  26. num--;
  27. }
  28. }
  29. dfs(row + 1); //本题的精髓:
  30. }
  31. int main() {
  32. while (~scanf_s("%d%d", &n, &k)) {
  33. if (n == -1 && k == -1) break;
  34. /*init*/
  35. memset(a, 0, sizeof(a));
  36. memset(map, 0, sizeof(map));
  37. ans = 0;
  38. num = 0;
  39. /*input*/
  40. for (int i = 1; i <= n; i++) {
  41. for (int j = 1; j <= n; j++) {
  42. cin >> map[i][j];
  43. }
  44. }
  45. /*dfs*/
  46. dfs(1);
  47. /*output*/
  48. cout << "ans = " << ans;
  49. }
  50. return 0;
  51. }

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) //判断是否被走过了

    1. return false;

    if (x >= n || x < 0 || y >= m || y < 0) //判断是否越界

    1. return false;

    return true; } void dfs(int x,int y) { if (step == n * m - 1) { ans++; return; } for (int i = 0; i < 8; i++) {

    1. if (!checkSteps(x + dir1[i], y + dir2[i])) continue;
    2. step++;
    3. vis[x][y] = 1;
    4. dfs(x + dir1[i], y + dir2[i]);
    5. step--; //回溯
    6. 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; } ```