(一)题记

从去年下半年开始找工作,大大小小也被“鄙”试、“面”试了n多回了。说实话只怪自己并未对常见的笔试题、面试题进行准备,导致败下阵来。一门学问要想学透学精是需要时间的,慢慢来吧……

第一次听到“八皇后”问题是在参加百度计算机视觉算法工程师面试时听中科院来面试的一个博士说的,当时隐约记得他是搞机器学习、模式识别的,所以自己以为这是很难的一个问题,回来简单想了一下也就没有细究。到后来去本行业初创公司“春雨”面试的时候,面试官让当场码代码解决这个问题,由于之前有印象,就定式思维地一直以为很难,所以从开始内心有些许的恐惧,最后在面试官的提示下写了个大概,最终结果不是很令人满意。

废话不多说了,一句话“不要被思维定式所困扰“,其实很简单的一个问题。

下面直奔主题:

(二)问题

http://zh.wikipedia.org/wiki/八皇后问题

八皇后问题是一个以国际象棋为背景的问题:如何能够在 8×8 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。八皇后问题可以推广为更一般的n皇后摆放问题:这时棋盘的大小变为n×n,而皇后个数也变成n。当且仅当 n = 1 或 n ≥ 4 时问题有解。

(三)思路分析

其实该问题并不难,利用递归方法很容易解决。没放置一个皇后,就将其能够攻击的区域进行标记,然后放置下一个皇后,一次类推……;此外,如果有解最终肯定是每一行有且只有一位皇后,所以放置的时候按照逐行放置的顺序进行。此问题难点在于如何把控递归函数的返回条件,一种条件是8个皇后放置完成后,返回成功,一种条件是该行中已经没有可以放置的位置,此时返回失败,需要重新放置。此时要额外注意,所谓的“重新放置”指的并不是将所有皇后清除重新来过,而是只返回上一层,将上一个导致本次放置失败的皇后进行清除,然后重新更新其位置,通过逐级放置、或逐级回溯可以达到遍历所有情况找到所有解(下文中给出的自己的代码的计算结果不是独立解的个数,而是所有可行解的情况)

(四)自己码代码

//--------------------------------------
//利用函数递归,解决八皇后问题
//
//  zssure  2014-03-12
//--------------------------------------#include <stdio.h>
#include <cmath>int count=0;//全局计数变量/*--------------------四个皇后----------------------*/
//#define QUEEN_NUM 4
//int label[QUEEN_NUM][QUEEN_NUM]={    0,0,0,0,
//                                  0,0,0,0,
//                                  0,0,0,0,
//                                  0,0,0,0 };/*--------------------五个皇后----------------------*/
//#define QUEEN_NUM 5
//int label[QUEEN_NUM][QUEEN_NUM]={    0,0,0,0,0,
//                                  0,0,0,0,0,
//                                  0,0,0,0,0,
//                                  0,0,0,0,0,
//                                  0,0,0,0,0       };/*--------------------六个皇后----------------------*/
//#define QUEEN_NUM 6
//int label[QUEEN_NUM][QUEEN_NUM]={    0,0,0,0,0,0,
//                                  0,0,0,0,0,0,
//                                  0,0,0,0,0,0,
//                                  0,0,0,0,0,0,
//                                  0,0,0,0,0,0,
//                                  0,0,0,0,0,0
//                                                  };/*--------------------七个皇后----------------------*/
//#define QUEEN_NUM 7
//int label[QUEEN_NUM][QUEEN_NUM]={    0,0,0,0,0,0,0,
//                                  0,0,0,0,0,0,0,
//                                  0,0,0,0,0,0,0,
//                                  0,0,0,0,0,0,0,
//                                  0,0,0,0,0,0,0,
//                                  0,0,0,0,0,0,0,
//                                  0,0,0,0,0,0,0
//                                                  };/*--------------------八个皇后----------------------*/
#define QUEEN_NUM 8
int label[QUEEN_NUM][QUEEN_NUM]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};void FillChessbox(int m,int n,int num)
{for(int i=0;i<QUEEN_NUM;++i)for(int j=0;j<QUEEN_NUM;++j)if(abs(i-m)==abs(j-n))//对角区域填充{if(label[i][j]==0)label[i][j]=num;}int i=0,j=0;while(i<QUEEN_NUM)//行填充{if(label[i][n]==0)label[i][n]=num;++i;}while(j<QUEEN_NUM)//列填充{if(label[m][j]==0)    label[m][j]=num;++j;}}
void ClearChessBox(int m,int n,int num)
{for(int i=0;i<QUEEN_NUM;++i)for(int j=0;j<QUEEN_NUM;++j)if(abs(i-m)==abs(j-n) && label[i][j]==num)label[i][j]=0;int i=0,j=0;while(i<QUEEN_NUM){if(label[i][n]==num)label[i][n]=0;++i;}while(j<QUEEN_NUM){if(label[m][j]==num)label[m][j]=0;++j;}
}
void AllClear()
{for(int i=0;i<QUEEN_NUM;++i)for(int j=0;j<QUEEN_NUM;++j)label[i][j]=0;}
void PrintResult()
{for(int i=0;i<QUEEN_NUM;++i){for(int j=0;j<QUEEN_NUM;++j)printf("%d ",label[i][j]);printf("\n");}
}
bool EightQueen(int n/*皇后个数*/,int c/*已经放置的皇后个数*/)
{//static int count=0;//小于3x3的棋盘是无解的if(n<4)return false;for(int i=0;i<n;++i){if(label[c-1][i]==0)//存在可以放置第c个皇后的位置{label[c-1][i]=c+1;if(c==n)/*已经放置完毕所有的皇后*/{++count;PrintResult();printf("**************************\n");ClearChessBox(c-1,i,c+1);//AllClear();return true;}FillChessbox(c-1,i,c+1);EightQueen(n,c+1);ClearChessBox(c-1,i,c+1);/*-------------------------------------------------------------------------------------------------------------------------//    现场恢复,无论下一个皇后是否顺利放置,都应该恢复现场。原因是////    如果下一个皇后放置失败,那么自然应该将本次放置的皇后去除,重新放置,所以需要进行现场恢复(即回溯);//  如果下一个皇后放置成功,意味着本次放置已经满足条件,是一个解,此时需要恢复现场,进行下一次的重新放置,寻找下一个解。////------------------------------------------------------------------------------------------------------------------------*///if(!EightQueen(n,c+1))//  ClearChessBox(c-1,i,c+1);}}return false;
}int main()
{EightQueen(QUEEN_NUM,1);printf("%d\n",count);return 0;
}

【注】:本次的代码使用了二维数组来标记皇后的位置,且最后输出结果中皇后位置并未准确显示,还有待改进。
参考博文:

http://blog.csdn.net/feixiaoxing/article/details/6877965

http://blog.csdn.net/sandyzhs/article/details/4250563

Author:zssure

E-mail:zssure@163.com

Date:2014-03-12

算法学习笔记之三:八皇后问题(递归、回溯)相关推荐

  1. 图解算法学习笔记(八):贪婪算法

    目录 (1)背包问题 (2)集合覆盖问题 (3)NP完全问题 (4)小结 本章内容: 学习如何处理没有快速算法的问题(NP完全问题). 学习近似算法,使用它们找到NP问题的近似解. 学习贪婪策略. ( ...

  2. 图解算法学习笔记(三):递归

    本章内容: 学习递归:如何将问题分解成基线条件和递归条件.     1) 每个递归函数都有两部分:基线条件(base case)和递归条件(recursive base).例如:打印3...2...1 ...

  3. 数据结构与算法学习笔记4:递归+分治法

    数据结构与算法学习笔记4 递归 斐波那契数列 青蛙跳台阶问题 链表倒序打印 分治法 二分查找/折半查找 Binary Search 题目1:快速幂 题目2:如何判断一个数是否为2的次幂 递归 指在函数 ...

  4. 《算法图解》学习笔记(八):贪婪算法和NP完全问题(附代码)

    欢迎关注WX公众号:[程序员管小亮] python学习之路 - 从入门到精通到大师 文章目录 欢迎关注WX公众号:[程序员管小亮] [python学习之路 - 从入门到精通到大师](https://b ...

  5. 陈宝林《最优化理论与算法》超详细学习笔记 (八)————最优性条件

    陈宝林<最优化理论与算法>超详细学习笔记 (八)----最优性条件 无约束问题的极值条件 必要条件 二阶充分条件 充要条件 约束极值问题的最优性条件 不等式约束的一阶最优性条件 无约束问题 ...

  6. 八皇后时间复杂度_回溯算法 | 追忆那些年曾难倒我们的八皇后问题

    文章收录在公众号:bigsai,关注更多干货和学习资源 记得点赞.在看 前言 说起八皇后问题,它是一道回溯算法类的经典问题,也可能是我们大部分人在上数据结构或者算法课上遇到过的最难的一道题-- 在这里 ...

  7. l2-004 这是二叉搜索树吗?_算法学习笔记(45): 二叉搜索树

    二叉搜索树(Binary Search Tree, BST)是一种常用的数据结构,在理想情况下,它可以以 的复杂度完成一系列修改和查询,包括: 插入一个数 删除一个数 查询某数的排名(排名定义为比该数 ...

  8. 两个字符串的最长公共子序列长度_算法学习笔记(58): 最长公共子序列

    (为什么都更了这么多篇笔记了,这时候才讲这么基础的内容呢?因为我本来以为LCS这种简单的DP不用讲的,结果CF不久前考了LCS的变式,然后我发现由于自己对LCS一点都不熟,居然写不出来 ,于是决定还是 ...

  9. 【基础】基础算法学习笔记(状态空间)

    基础算法学习笔记(状态空间) 一.状态空间 1.定义(什么是状态空间):一个实际问题的各种可能情况构成的集合.(解释:为什么需要算法来和程序来处理问题?如果一道题可以手算得到答案,换句话说就是存在通过 ...

最新文章

  1. flex 文字竖排_flex button字竖排展示
  2. 台式电脑不拉网线上网_技巧知识:电脑不用网线也可以上网了,你知道吗?
  3. vue垂直布局_vue实现长图垂直居上 vue实现短图垂直居中
  4. git init、git status、git config user.name、git add、git commit、git remote、git push、git clone、git pull
  5. python全景图像拼接_超详讲解图像拼接/全景图原理和应用 | 附源码
  6. python-各种tips
  7. pthread 立即停止线程_iOS多线程:『pthread、NSThread』详尽总结
  8. 【历史上的今天】8 月 14 日:新浪微博开始内测;阿塔纳索夫完成论文;登上太空的计算机病毒
  9. 油猴(Tampermonkey)插件+脚本+IDM=百度网盘高速下载
  10. 『码上行动-编程擂台』学员作品展(附源码)
  11. 《密码学系列》—— 流密码
  12. 上海市四金和税的算法
  13. APP软件开发定制返利网分销商城APP
  14. IOS系统ipa软件包在线安装
  15. 通过指定cellid获取周围cellid信息,改变指定cellid的颜色
  16. 有WINDOWS为何还学DOS?【转载】
  17. Python 列表(list)
  18. setContentView(R.layout.xxx)出错解决方法
  19. 一对一视频聊天app源码,Android开发之取两个色值的中间色
  20. 一份很全的路由器默认初始密码集合

热门文章

  1. L4独角兽突然死亡!狂烧259亿,背靠老牌车企,依然难逃今日结局
  2. [论文阅读] (18)英文论文Model Design和Overview如何撰写及精句摘抄——以系统AI安全顶会为例
  3. 对标西湖大学、投资超460亿!这所新大学发布全球招聘公告!
  4. 学习盘口语言--转载
  5. AI高校排行榜:2018年度全国普通高校人工智能方向本科教育教学综合实力排行榜...
  6. 百度地图技术赋能智能硬件 推动行业安全、智能化发展
  7. c语言isnumber函数的使用方法,无法使用isNumber函数?
  8. 最新公益课PHP、Vue、Uniapp、微信、Laravel等【共18部公益课】
  9. 半导体(芯片制造)材料概述
  10. 字体转换unicode