• N皇后问题


     【八皇后问题】

    在棋盘上放置8个皇后,使得她们互不攻击,此时每个皇后的攻击范围为同行同列和同对角线,要求找出所有解。

    【回溯】:当把问题分成若干步骤并递归求解时,如果当前步骤没有合法选择,则函数将返回上一级递归调用,这种现象称为回溯。递归枚举算法通常被称为回溯法。

      1 #include <stdio.h>
      2 
      3 #define QUEEN_N     (8)
      4 
      5 int queen[QUEEN_N][QUEEN_N] = {
      6     {0, 0, 0, 0, 0, 0, 0, 0},
      7     {0, 0, 0, 0, 0, 0, 0, 0},
      8     {0, 0, 0, 0, 0, 0, 0, 0},
      9     {0, 0, 0, 0, 0, 0, 0, 0},
     10     {0, 0, 0, 0, 0, 0, 0, 0},
     11     {0, 0, 0, 0, 0, 0, 0, 0},
     12     {0, 0, 0, 0, 0, 0, 0, 0},
     13     {0, 0, 0, 0, 0, 0, 0, 0},
     14 };
     15 
     16 int queen_check(int x, int y)
     17 {
     18     int i;
     19 
     20     for(i = 0; i < QUEEN_N; i++)
     21     {
     22         if(queen[i][y] == 1 && i != x) // 检测列
     23             return 0;
     24         if(queen[x][i] == 1 && i != y) // 检测行
     25             return 0;
     26     }
     27 
     28     // 检测对角线,x正向方向
     29     for(i = x+1; i < QUEEN_N; i++)
     30     {
     31         if(y + i - x < QUEEN_N)
     32             if(queen[i][y+i-x] == 1)
     33                 return 0;
     34         if(y - (i - x) >= 0)
     35             if(queen[i][y-i+x] == 1)
     36                 return 0;
     37     }
     38     // 检测对角线,x反向方向
     39     for(i = x-1; i >=0; i--)
     40     {
     41         if(y + (x-i) < QUEEN_N)
     42             if(queen[i][y+x-i] == 1)
     43                 return 0;
     44         if(y - (x-i) >= 0)
     45             if(queen[i][y-x+i] == 1)
     46                 return 0;
     47     }
     48     return 1;
     49 }
     50 
     51 void queen_print(int queen[QUEEN_N][QUEEN_N]) // 输出棋盘布局
     52 {
     53     int i, j;
     54 
     55     for(i = 0; i < QUEEN_N; i++)
     56     {
     57         for(j = 0; j < QUEEN_N; j++)
     58         {
     59             if(queen[i][j] == 1)
     60             {
     61                 printf("O ");
     62             }
     63             else
     64             {
     65                 printf("x ");
     66             }
     67         }
     68         printf("
    ");
     69     }
     70 }
     71 
     72 // 输出所有棋盘
     73 void queen_fill(int n)
     74 {
     75     int i;
     76     static int iCount = 0;
     77     if(n >= QUEEN_N) // 递归边界。只要走到了这里,所有皇后必然不冲突。
     78     {
     79         printf("queen_print <%d>
    ", iCount++);
     80         queen_print(queen);
     81     }
     82     else
     83     {
     84         for(i = 0; i < QUEEN_N; i++) // 尝试把第n行的皇后放在第i列
     85         {
     86             queen[n][i] = 1;
     87             if(queen_check(n, i) == 1)
     88             {
     89                 queen_fill(n+1); // 如果合法,则继续递归,放置下一行
     90             }
     91             queen[n][i] = 0;
     92         }
     93     }
     94 }
     95 // 输出第1个棋盘
     96 int queen_fill_1(int n)
     97 {
     98     int i;
     99     if(n >= QUEEN_N)
    100     {
    101         queen_print(queen);
    102         return 1;
    103     }
    104     else
    105     {
    106         for(i = 0; i < QUEEN_N; i++)
    107         {
    108             queen[n][i] = 1;
    109             if(queen_check(n, i) == 1)
    110             {
    111                 if(queen_fill_1(n+1) == 1)
    112                     return 1;
    113             }
    114             queen[n][i] = 0;
    115         }
    116     }
    117     return 0;
    118 }
    119 
    120 // 对于原始棋盘,判断是否能输出满足的棋盘
    121 int queen_fill_x(int n)
    122 {
    123     int i;
    124     if(n >= QUEEN_N)
    125     {
    126         queen_print(queen);
    127         return 1;
    128     }
    129     else
    130     {
    131         for(i = 0; i < QUEEN_N; i++)
    132         {
    133             if(queen[n][i] == 0)
    134             {
    135                 queen[n][i] = 1;
    136                 if(queen_check(n, i) == 1)
    137                 {
    138                     if(queen_fill_x(n+1) == 1)
    139                         return 1;
    140                 }
    141                 queen[n][i] = 0;
    142             }
    143             else
    144             {
    145                 if(queen_check(n, i) == 1)
    146                 {
    147                     if(queen_fill_x(n+1) == 1)
    148                         return 1;
    149                 }
    150             }
    151         }
    152     }
    153     return 0;
    154 }
    155 
    156 int main(void)
    157 {
    158     int iRet;
    159     printf("init queen:
    ");
    160     queen_print(queen);
    161 
    162     printf("queen_fill_x:
    ");
    163     iRet = queen_fill_x(0);
    164     if(iRet != 1)
    165     {
    166         printf("xxx err
    ");
    167     }
    168 
    169     printf("queen_fill_1:
    ");
    170     queen_fill_1(0);
    171 
    172     printf("queen_fill_all:
    ");
    173     queen_fill(0);
    174 
    175     return 0;
    176 }

    在编写递归枚举程序之前,需要深入分析问题,对模型精雕细琢。一般还应对解答树的结点数有一个粗略的估计,作为对评价模型的重要依据。

    递归解决问题的思想:

    if 问题足够简单:

      直接解决问题

      返回解

    else:

      将问题分解为与原问题同构的一个或多个更小的问题

      逐个解决这些更小的问题

      将结果组合为,获得最终的解

      返回解

  • 相关阅读:
    路漫漫的自学之路(1)
    feel better about yourself 完美破解MyEclipse 5.5.1 GA 注册码呵呵
    prctise .cpp & .h 的拆分
    JsDemo
    intro
    英汉词典
    曾国藩名言
    挫折
    去掉‘为帮助保护您的安全,internet explorer已经限制此文件显示可能访问您的计算机的活动内容’提示
    曾国藩对联欣赏
  • 原文地址:https://www.cnblogs.com/utank/p/4330244.html
Copyright © 2020-2023  润新知