zoukankan      html  css  js  c++  java
  • 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:

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

      逐个解决这些更小的问题

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

      返回解

  • 相关阅读:
    Algebra, Topology, Differential Calculus, and Optimization Theory For Computer Science and Machine Learning 第50章 读书笔记(待更新)
    Algebra, Topology, Differential Calculus, and Optimization Theory For Computer Science and Machine Learning 第49章 读书笔记(待更新)
    Algebra, Topology, Differential Calculus, and Optimization Theory For Computer Science and Machine Learning 第48章 读书笔记(待更新)
    Spring Boot 中使用 Quartz 实现任务调度
    实战 FastDFS Java 客户端上传文件
    分布式文件系统之 FastDFS
    Java 持久层框架之 MyBatis
    C语言实现贪吃蛇
    [转载]分享三篇非常好的学习心得
    selenium加载cookie报错问题:selenium.common.exceptions.InvalidCookieDomainException: Message: invalid cookie domain
  • 原文地址:https://www.cnblogs.com/utank/p/4330244.html
Copyright © 2011-2022 走看看