鱼C论坛

 找回密码
 立即注册
查看: 2674|回复: 5

[已解决]小甲鱼课后作业S1E36马踏棋盘问题

[复制链接]
发表于 2021-12-10 23:06:20 | 显示全部楼层 |阅读模式
15鱼币
请问各位大佬们,我的回溯算法为什么会死循环?
  1. #include <stdio.h>

  2. const int step[8][2] = {{-1,-2},{1,-2},{-2,-1},{2,-1},{-1,2},{-2,1},{1,2},{2,1}};
  3. int array[8][8] = {0};
  4. int end(int (*array)[8]);

  5. int run(int row,int col,int (*array)[8])
  6. {
  7.         int i;
  8.         printf("%2d ",(row - 1) * 8 + col);
  9.         if (end(array))
  10.         {
  11.                 printf("success");
  12.                 return 1;
  13.         }
  14.         for (i = 0;i < 8;i++)
  15.         {
  16.                 if (row + step[i][0] >= 1 && col + step[i][1] >= 1 && row + step[i][0] <= 8 && col + step[i][0] <= 8 && !array[row + step[i][0] - 1][col + step[i][1] - 1])
  17.                 {
  18.                         array[row + step[i][0] - 1][col + step[i][1] - 1] = (row + step[i][0] - 1) * 8 + (col + step[i][1]);
  19.                         run(row + step[i][0],col + step[i][1],array);
  20.                         printf("\b\b\b   ");
  21.                         array[row + step[i][0] - 1][col + step[i][1] - 1] = 0;
  22.                 }
  23.         }
  24.         return 0;
  25. }

  26. int end(int (*array)[8])
  27. {
  28.         for (int i = 0;i < 8;i++)
  29.         {
  30.                 for (int j = 0;j < 8;j++)
  31.                 {
  32.                         if (!array[i][j])
  33.                         {
  34.                                 return 0;
  35.                         }
  36.                 }
  37.         }
  38.         return 1;
  39. }

  40. int main(void)
  41. {
  42.         int row,col;
  43.         printf("请输入行数:");
  44.         scanf("%d",&row);
  45.         printf("请输入列数:");
  46.         scanf("%d",&col);
  47.         array[row - 1][col - 1] = (row - 1) * 8 + col;
  48.         run(row,col,array);
  49.        
  50.         return 0;
  51. }
复制代码
最佳答案
2021-12-10 23:06:21
你代码逻辑就是错的吧?
还有写代码不认真
  1. #include <stdio.h>

  2. const int step[8][2] = {{-1, -2}, {1, -2}, {-2, -1}, {2, -1}, {-1, 2}, {-2, 1}, {1, 2}, {2, 1}};
  3. int array[8][8] = {0};
  4. int end(int (*array)[8]);

  5. int run(int row, int col, int (*array)[8]) {
  6.     int i;
  7.     //printf("%2d ", (row - 1) * 8 + col);
  8.     if(end(array)) {
  9.         //printf("success");
  10.         printf("success\n");
  11.         return 1;
  12.     }
  13.     for(i = 0; i < 8; i++) {
  14.         if(row + step[i][0] >= 1 && col + step[i][1] >= 1 &&
  15.            // 认真一点
  16.            //row + step[i][0] <= 8 && col + step[i][0] <= 8 &&
  17.            row + step[i][0] <= 8 && col + step[i][1] <= 8 &&
  18.            !array[row + step[i][0] - 1][col + step[i][1] - 1]) {
  19.             array[row + step[i][0] - 1][col + step[i][1] - 1] =
  20.                 (row + step[i][0] - 1) * 8 + (col + step[i][1]);

  21.             // 上面都减1,这里怎么不减1了?
  22.             //run(row + step[i][0], col + step[i][1], array);
  23.             run(row + step[i][0] - 1, col + step[i][1] - 1, array);
  24.             //printf("\b\b\b   ");
  25.             array[row + step[i][0] - 1][col + step[i][1] - 1] = 0;
  26.         }
  27.     }
  28.     return 0;
  29. }

  30. int end(int (*array)[8]) {
  31.     for(int i = 0; i < 8; i++) {
  32.         for(int j = 0; j < 8; j++) {
  33.             if(!array[i][j]) {
  34.                 return 0;
  35.             }
  36.         }
  37.     }
  38.     return 1;
  39. }

  40. int main(void) {
  41.     int row, col;
  42.     printf("请输入行数:");
  43.     scanf("%d", &row);
  44.     printf("请输入列数:");
  45.     scanf("%d", &col);

  46.     // 这是在做什么?
  47.     array[row - 1][col - 1] = (row - 1) * 8 + col;

  48.     run(row, col, array);

  49.     return 0;
  50. }
复制代码

最佳答案

查看完整内容

你代码逻辑就是错的吧? 还有写代码不认真
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-12-10 23:06:21 | 显示全部楼层    本楼为最佳答案   
你代码逻辑就是错的吧?
还有写代码不认真
  1. #include <stdio.h>

  2. const int step[8][2] = {{-1, -2}, {1, -2}, {-2, -1}, {2, -1}, {-1, 2}, {-2, 1}, {1, 2}, {2, 1}};
  3. int array[8][8] = {0};
  4. int end(int (*array)[8]);

  5. int run(int row, int col, int (*array)[8]) {
  6.     int i;
  7.     //printf("%2d ", (row - 1) * 8 + col);
  8.     if(end(array)) {
  9.         //printf("success");
  10.         printf("success\n");
  11.         return 1;
  12.     }
  13.     for(i = 0; i < 8; i++) {
  14.         if(row + step[i][0] >= 1 && col + step[i][1] >= 1 &&
  15.            // 认真一点
  16.            //row + step[i][0] <= 8 && col + step[i][0] <= 8 &&
  17.            row + step[i][0] <= 8 && col + step[i][1] <= 8 &&
  18.            !array[row + step[i][0] - 1][col + step[i][1] - 1]) {
  19.             array[row + step[i][0] - 1][col + step[i][1] - 1] =
  20.                 (row + step[i][0] - 1) * 8 + (col + step[i][1]);

  21.             // 上面都减1,这里怎么不减1了?
  22.             //run(row + step[i][0], col + step[i][1], array);
  23.             run(row + step[i][0] - 1, col + step[i][1] - 1, array);
  24.             //printf("\b\b\b   ");
  25.             array[row + step[i][0] - 1][col + step[i][1] - 1] = 0;
  26.         }
  27.     }
  28.     return 0;
  29. }

  30. int end(int (*array)[8]) {
  31.     for(int i = 0; i < 8; i++) {
  32.         for(int j = 0; j < 8; j++) {
  33.             if(!array[i][j]) {
  34.                 return 0;
  35.             }
  36.         }
  37.     }
  38.     return 1;
  39. }

  40. int main(void) {
  41.     int row, col;
  42.     printf("请输入行数:");
  43.     scanf("%d", &row);
  44.     printf("请输入列数:");
  45.     scanf("%d", &col);

  46.     // 这是在做什么?
  47.     array[row - 1][col - 1] = (row - 1) * 8 + col;

  48.     run(row, col, array);

  49.     return 0;
  50. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2021-12-11 09:54:43 | 显示全部楼层
  1. step = [[-1,-2],[1,-2],[-2,-1],[2,-1],[-1,2],[-2,1],[1,2],[2,1]]
  2. array = [[0 for j in range(8)] for i in range(8)]

  3. def end(array):
  4.     for i in range(8):
  5.         for j in range(8):
  6.             if (not array[i][j]):
  7.                 return False
  8.     return True


  9. def run(row,col,array):
  10.     print((row - 1) * 8 + col)
  11.     if (end(array)):
  12.         print("success")
  13.         return True
  14.     print(row)
  15.     print(col)
  16.     for i in range(8):
  17.         if (row + step[i][0] >= 1 and col + step[i][1] >= 1 and row + step[i][0] <= 8 and col + step[i][0] <= 8 and not array[row + step[i][0] - 1][col + step[i][1] - 1]):
  18.             array[row + step[i][0] - 1][col + step[i][1] - 1] = (row + step[i][0] - 1) * 8 + (col + step[i][1])
  19.             run(row + step[i][0],col + step[i][1],array)
  20.             print("\b\b\b   ")
  21.             array[row + step[i][0] - 1][col + step[i][1] - 1] = 0
  22.     return False

  23. def main(row,col):
  24.     array[row - 1][col - 1] = 18
  25.     run(row,col,array)
  26.     return True

  27. if __name__ == "__main__":
  28.     main(3,2)
复制代码

我试了下Python写,他说我列表越界了,有没有大佬帮帮忙
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-12-12 11:53:15 | 显示全部楼层
我先贴一下我的代码,等一下看你写的代码

  1. #include <stdio.h>
  2. #include <stdbool.h>
  3. #include <time.h>

  4. const int step[8][2] = {{-1, -2}, {1, -2}, {-2, -1}, {2, -1}, {-2, 1},  {2, 1},  {-1, 2},  {1, 2}};
  5. size_t array[8][8];

  6. bool verify(void) {
  7.     for(size_t y = 0; y < 8; ++y) {
  8.         for(size_t x = 0; x < 8; ++x) {
  9.             if(!array[y][x]) return false;
  10.         }
  11.     }
  12.     return true;
  13. }

  14. bool exist(size_t x, size_t y) {
  15.     if(x >= 8) return false;
  16.     if(y >= 8) return false;
  17.     return true;
  18. }

  19. bool run(size_t x, size_t y, size_t count) {
  20.     if(verify()) return true;
  21.     if(!exist(x, y)) return false;
  22.     if(array[y][x]) return false;
  23.     bool flag = false;
  24.     array[y][x] = count;
  25.     for(size_t i = 0; i < 8; ++i) {
  26.         size_t nx = x + step[i][0];
  27.         size_t ny = y + step[i][1];
  28.         if((flag = run(nx, ny, count + 1))) break;
  29.     }
  30.     if(!flag) array[y][x] = 0;
  31.     return flag;
  32. }

  33. int main(void) {
  34.     time_t begin = time(NULL);
  35.     run(2, 0, 1);
  36.     for(size_t y = 0; y < 8; ++y) {
  37.         for(size_t x = 0; x < 8; ++x) {
  38.             printf("%2lu ", array[y][x]);
  39.         }
  40.         puts("");
  41.     }
  42.     time_t end = time(NULL);
  43.     printf("time: %lu\n", end - begin);
  44.     return 0;
  45. }
复制代码

  1. $ gcc -O3 -o main main.c
  2. $ ./main
  3. 11  4  1 18  9  6 15 64
  4. 2 19 10  5 14 17 24  7
  5. 39 12  3 20 23  8 63 16
  6. 30 21 38 13 28 25 46 61
  7. 37 40 29 22 47 62 51 26
  8. 34 31 36 55 52 27 60 45
  9. 41 56 33 48 43 58 53 50
  10. 32 35 42 57 54 49 44 59
  11. time: 496
  12. $
复制代码


O3 优化都 496 秒,^_^


对于我的这个代码,第一次选的是题目中的位置
  1.     run(4, 3, 1);
复制代码

  1. $ gcc -O3 -o main main.c
  2. $ ./main
  3. 6  3  8 11 14 17 20 23
  4. 9 12  5  2 21 24 15 18
  5. 4  7 10 13 16 19 22 25
  6. 31 28 41 36  1 26 49 38
  7. 42 35 30 27 40 37 60 47
  8. 29 32 55 44 61 48 39 50
  9. 54 43 34 57 52 63 46 59
  10. 33 56 53 62 45 58 51 64
  11. time: 22
  12. $
复制代码


O3 优化,22 秒

这个使用时间的多少,和起点的选择有关
还和step数组中的元素排列顺序有关

想要得到一个用时最短的组合(起点和step数组中的元素排列顺序)
需要对每一个起点去尝试step数组的全排列,这需要相当长的时间
我就不找这个组合了

我试了一下答案,6秒
  1. #include <stdio.h>
  2. #include <time.h>

  3. #define X 8
  4. #define Y 8

  5. int chess[X][Y];

  6. // 找到下一个可走的位置
  7. int next(int *px, int *py, int count)
  8. {
  9.         int x = *px;
  10.         int y = *py;

  11.         switch(count)
  12.         {
  13.         case 0:
  14.                 if (x+2<=X-1 && y-1>=0 && chess[x+2][y-1] == 0)
  15.                 {
  16.                         *px = x + 2;
  17.                         *py = y - 1;
  18.                         return 1;
  19.                 }
  20.                 break;
  21.         case 1:
  22.                 if (x+2<=X-1 && y+1<=Y-1 && chess[x+2][y+1] == 0)
  23.                 {
  24.                         *px = x + 2;
  25.                         *py = y + 1;
  26.                         return 1;
  27.                 }
  28.                 break;
  29.         case 2:
  30.                 if (x+1<=X-1 && y-2>=0 && chess[x+1][y-2] == 0)
  31.                 {
  32.                         *px = x + 1;
  33.                         *py = y - 2;
  34.                         return 1;
  35.                 }
  36.                 break;
  37.         case 3:
  38.                 if (x+1<=X-1 && y+2<=Y-1 && chess[x+1][y+2] == 0)
  39.                 {
  40.                         *px = x + 1;
  41.                         *py = y + 2;
  42.                         return 1;
  43.                 }
  44.                 break;
  45.         case 4:
  46.                 if (x-2>=0 && y-1>=0 && chess[x-2][y-1] == 0)
  47.                 {
  48.                         *px = x - 2;
  49.                         *py = y - 1;
  50.                         return 1;
  51.                 }
  52.                 break;
  53.         case 5:
  54.                 if (x-2>=0 && y+1<=Y-1 && chess[x-2][y+1] == 0)
  55.                 {
  56.                         *px = x - 2;
  57.                         *py = y + 1;
  58.                         return 1;
  59.                 }
  60.                 break;
  61.         case 6:
  62.                 if (x-1>=0 && y-2>=0 && chess[x-1][y-2] == 0)
  63.                 {
  64.                         *px = x - 1;
  65.                         *py = y - 2;
  66.                         return 1;
  67.                 }
  68.                 break;
  69.         case 7:
  70.                 if (x-1>=0 && y+2<=Y-1 && chess[x-1][y+2] == 0)
  71.                 {
  72.                         *px = x - 1;
  73.                         *py = y + 2;
  74.                         return 1;
  75.                 }
  76.                 break;
  77.         }

  78.         return 0;
  79. }

  80. int setHorse(int x, int y, int tag)
  81. {
  82.         int x1 = x, y1 = y, flag = 0, count = 0;

  83.         // tag记录轨迹
  84.         chess[x][y] = tag;
  85.         // 如果tag等于64退出程序
  86.         if (tag == X*Y)
  87.         {
  88.                 return 1;
  89.         }

  90.         // 如果可以走,那么flag为1
  91.         flag = next(&x1, &y1, count);
  92.         // 否则尝试其他路径
  93.         while (flag == 0 && count < 7)
  94.         {
  95.                 count += 1;
  96.                 flag = next(&x1, &y1, count);
  97.         }

  98.         // 递归进入下一个坐标
  99.         while (flag)
  100.         {
  101.                 // 返回1表示成功找到落脚点
  102.                 if (setHorse(x1, y1, tag+1))
  103.                 {
  104.                         return 1;
  105.                 }
  106.                 // 否则从上一步重新尝试
  107.                 x1 = x;
  108.                 y1 = y;
  109.                 count += 1;
  110.                 flag = next(&x1, &y1, count);
  111.                 while (flag == 0 && count < 7)
  112.                 {
  113.                         count += 1;
  114.                         flag = next(&x1, &y1, count);
  115.                 }
  116.         }

  117.         if (flag == 0)
  118.         {
  119.                 chess[x][y] = 0;
  120.         }

  121.         return 0;
  122. }

  123. int main(void)
  124. {
  125.     time_t begin = time(NULL);
  126.         int i, j;

  127.         for (i = 0; i < X; i++)
  128.         {
  129.                 for (j = 0; j < Y; j++)
  130.                 {
  131.                         chess[i][j] = 0;
  132.                 }
  133.         }

  134.         // 讲道理,从 (2, 0) 坐标开始计算是比较容易出结果的
  135.         // 如果你比较有耐心,或 CPU 特别强劲,可以尝试计算其它坐标
  136.         if (setHorse(2, 0, 1))
  137.         {
  138.                 for (i = 0; i < X; i++)
  139.                 {
  140.                         for (j = 0; j < Y; j++)
  141.                         {
  142.                                 printf("%02d  ", chess[i][j]);
  143.                         }
  144.                         putchar('\n');
  145.                 }
  146.         }
  147.         else
  148.         {
  149.                 printf("可惜无解!\n");
  150.         }
  151.     time_t end = time(NULL);
  152.     printf("time: %lu\n", end - begin);

  153.         return 0;
  154. }
复制代码

  1. $ gcc -O3 -o tmp tmp.c
  2. $ ./tmp
  3. 43  50  47  38  57  52  61  32
  4. 48  37  44  51  46  33  58  53
  5. 01  42  49  56  39  60  31  62
  6. 36  15  40  45  34  29  54  59
  7. 41  02  35  16  55  24  63  30
  8. 14  05  12  09  22  19  28  25
  9. 03  10  07  20  17  26  23  64
  10. 06  13  04  11  08  21  18  27
  11. time: 6
  12. $
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-12-12 12:43:11 | 显示全部楼层
  1. #include <stdio.h>
  2. #include <stdbool.h>
  3. #include <time.h>

  4. const int step[8][2] = {{2, -1}, {2, 1}, {1, -2}, {1, 2}, {-2, -1},  {-2, 1},  {-1, -2},  {-1, 2}};
  5. size_t array[8][8];

  6. bool verify(void) {
  7.     for(size_t y = 0; y < 8; ++y) {
  8.         for(size_t x = 0; x < 8; ++x) {
  9.             if(!array[y][x]) return false;
  10.         }
  11.     }
  12.     return true;
  13. }

  14. bool exist(size_t x, size_t y) {
  15.     if(x >= 8) return false;
  16.     if(y >= 8) return false;
  17.     return true;
  18. }

  19. bool run(size_t x, size_t y, size_t count) {
  20.     if(verify()) return true;
  21.     if(!exist(x, y)) return false;
  22.     if(array[y][x]) return false;
  23.     bool flag = false;
  24.     array[y][x] = count;
  25.     for(size_t i = 0; i < 8; ++i) {
  26.         size_t nx = x + step[i][0];
  27.         size_t ny = y + step[i][1];
  28.         if((flag = run(nx, ny, count + 1))) break;
  29.     }
  30.     if(!flag) array[y][x] = 0;
  31.     return flag;
  32. }

  33. int main(void) {
  34.     time_t begin = time(NULL);
  35.     run(2, 0, 1);
  36.     for(size_t y = 0; y < 8; ++y) {
  37.         for(size_t x = 0; x < 8; ++x) {
  38.             printf("%2lu ", array[y][x]);
  39.         }
  40.         puts("");
  41.     }
  42.     time_t end = time(NULL);
  43.     printf("time: %lu\n", end - begin);
  44.     return 0;
  45. }
复制代码

  1. $ gcc -O3 -o main main.c
  2. $ ./main
  3. 43 48  1 36 41 14  3  6
  4. 50 37 42 15  2  5 10 13
  5. 47 44 49 40 35 12  7  4
  6. 38 51 56 45 16  9 20 11
  7. 57 46 39 34 55 22 17  8
  8. 52 33 60 29 24 19 26 21
  9. 61 58 31 54 63 28 23 18
  10. 32 53 62 59 30 25 64 27
  11. time: 9
复制代码


接下来看你写的代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-12-12 17:29:36 | 显示全部楼层
作为练习,上面那个八皇后的问题,我也写了,有兴趣的话可以看一看

参考:https://www.jianshu.com/p/deb028537af2
基本思路是:
1.第一行先占一个皇后
2.第二行再占一个且不能与第一个皇后攻击
3.第三行再占一个
。。。。。

  1. #include <stdio.h>
  2. #include <stdbool.h>

  3. bool array[8][8];
  4. size_t count;

  5. bool verify(size_t y, size_t x) {
  6.     for(size_t cy = 0; cy < y; ++cy) {
  7.         if(array[cy][x]) return false;
  8.     }
  9.     for(size_t cy = y - 1, cx = x - 1; cy < 8 && cx < 8; --cy, --cx) {
  10.         if(array[cy][cx]) return false;
  11.     }
  12.     for(size_t cy = y - 1, cx = x + 1; cy < 8 && cx < 8; --cy, ++cx) {
  13.         if(array[cy][cx]) return false;
  14.     }
  15.     return true;
  16. }

  17. void run(size_t y) {
  18.     if(y >= 8) {
  19.         printf("count: %lu\n", ++count);
  20.         for(size_t y = 0; y < 8; ++y) {
  21.             for(size_t x = 0; x < 8; ++x) {
  22.                 printf("%u ", array[y][x]);
  23.             }
  24.             puts("");
  25.         }
  26.         return;
  27.     }
  28.     for(size_t x = 0; x < 8; ++x) {
  29.         if(!verify(y, x)) continue;
  30.         array[y][x] = true;
  31.         run(y + 1);
  32.         array[y][x] = false;
  33.     }
  34. }

  35. int main(void) {
  36.     run(0);
  37.     return 0;
  38. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-5-12 02:40

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表