N皇后问题的c++解法
2017-05-05 13:04
176 查看
N皇后问题:
国际象棋中皇后的势力范围覆盖其所在的行、列以及两条对角线,现在考察如下问题:如何在n x n的棋盘上放置n个皇后,使得她们彼此互不攻击
对于任何整数:n>=4,这就是n皇后问题。我们常说的8皇后问题也就是n为8的时候
首先,讲一讲思路,大致思路就是:我们把n个皇后分别放在n行中的第一个位置,然后挨行试探,回溯
譬如,第一个皇后在第一行第一列,试探下一行的皇后,将其放在不会与之前所有皇后冲突的某一列,然后再试探下一行的皇后,再把其放在不会与之前所有的皇后冲突的某一列,若当前皇后找不到一个不冲突的列放置,那就是说明上一个皇后放置的位置不对,我们再退回到上一行,把上一行的皇后位置往后挪,然后继续重复这个过程。
可见,
1、我们需要保存之前暂时确定下来的位置(因为需要判断当前皇后的位置会不会与之前所有的皇后位置起冲突)
2、并且可能需要回溯的做法,也就是把之前的一个位置删除,修改
所以,暂时看来,stack结构非常适合用来保存皇后的坐标,入栈出栈操作很方便
3、判断皇后位置是否冲突,也就是两个皇后的势力范围有没有交集,如(x1,y1) (x2,y2)这两个皇后的坐标,当且仅当:
x1 != x2 且 y1 != y2 且 (x1+y1) != (x2+y2) 且 (x1-y1) != (x2-y2)
的时候,这两个皇后才不冲突,所以定义一个皇后类(保存皇后坐标),重载其相等运算符,只要上面四个条件有一个不满足,则我们就认为这两个皇后相等,也就是“相冲突”
4、判断一个皇后是否与之前所有的皇后冲突,就要一一去遍历保存下来的皇后,判断其与当前的位置相等吗,而c++标准库的stack并不支持遍历操作,只能操作栈顶的元素,详情见我的另一篇博客:
stl:stack详解
所以这里我们不能用c++标准库的stack来保存坐标(当然自己定义的stack类,添加遍历功能的话还是可以用的),所以我选用了vector保存坐标,因为
1、vector模拟stack的入栈出栈很方便简洁
2、vector进行元素遍历很方便
,另注意,我们需要对vector保存的queen类元素进行赋值操作,所以还要重载皇后类的赋值运算符
所以定义如下皇后类:
问题分析完了,数据结构选用完了,下面就是实现这个算法了,代码与注释如下:
4皇后,运行结果:
5皇后,运行结果:
6皇后,运行结果:
7皇后,运行结果:
8皇后,运行结果:
国际象棋中皇后的势力范围覆盖其所在的行、列以及两条对角线,现在考察如下问题:如何在n x n的棋盘上放置n个皇后,使得她们彼此互不攻击
对于任何整数:n>=4,这就是n皇后问题。我们常说的8皇后问题也就是n为8的时候
首先,讲一讲思路,大致思路就是:我们把n个皇后分别放在n行中的第一个位置,然后挨行试探,回溯
譬如,第一个皇后在第一行第一列,试探下一行的皇后,将其放在不会与之前所有皇后冲突的某一列,然后再试探下一行的皇后,再把其放在不会与之前所有的皇后冲突的某一列,若当前皇后找不到一个不冲突的列放置,那就是说明上一个皇后放置的位置不对,我们再退回到上一行,把上一行的皇后位置往后挪,然后继续重复这个过程。
可见,
1、我们需要保存之前暂时确定下来的位置(因为需要判断当前皇后的位置会不会与之前所有的皇后位置起冲突)
2、并且可能需要回溯的做法,也就是把之前的一个位置删除,修改
所以,暂时看来,stack结构非常适合用来保存皇后的坐标,入栈出栈操作很方便
3、判断皇后位置是否冲突,也就是两个皇后的势力范围有没有交集,如(x1,y1) (x2,y2)这两个皇后的坐标,当且仅当:
x1 != x2 且 y1 != y2 且 (x1+y1) != (x2+y2) 且 (x1-y1) != (x2-y2)
的时候,这两个皇后才不冲突,所以定义一个皇后类(保存皇后坐标),重载其相等运算符,只要上面四个条件有一个不满足,则我们就认为这两个皇后相等,也就是“相冲突”
4、判断一个皇后是否与之前所有的皇后冲突,就要一一去遍历保存下来的皇后,判断其与当前的位置相等吗,而c++标准库的stack并不支持遍历操作,只能操作栈顶的元素,详情见我的另一篇博客:
stl:stack详解
所以这里我们不能用c++标准库的stack来保存坐标(当然自己定义的stack类,添加遍历功能的话还是可以用的),所以我选用了vector保存坐标,因为
1、vector模拟stack的入栈出栈很方便简洁
2、vector进行元素遍历很方便
,另注意,我们需要对vector保存的queen类元素进行赋值操作,所以还要重载皇后类的赋值运算符
所以定义如下皇后类:
struct Queen { unsigned int x, y; Queen(unsigned int xx = 0, unsigned int yy = 0) :x(xx), y(yy){}; //重载相等与不等运算符 bool operator==(const Queen& qa)const { return(x == qa.x || y == qa.y || (x + y) == (qa.x + qa.y) || (x - y) == (qa.x - qa.y)); } bool operator!=(Queen const& qa)const { return !(*this == qa); } //重载赋值运算符 Queen& operator=(Queen const& qa) { x = qa.x; y = qa.y; return *this; } };
问题分析完了,数据结构选用完了,下面就是实现这个算法了,代码与注释如下:
//皇后类 #include<stack> #include<vector> #include<algorithm> void myN_Queens(unsigned int N) { vector<Queen> result; Queen q(0, 0); unsigned int row = 0;//标记当前在操作的行,当操作到了最后一行的后面,就代表可以结束了 while (row < N) { while ((q.y < N) && (result.end() != find(result.begin(), result.end(), q))) //直到在本行找到一个位置或者到了行尾,不然就一直往右移试探本行的下一位置 { q.y++; } if (N > q.y)//如果没到行尾,也就是在本行找到了一个合适的位置 { result.insert(result.end(), q);//把此时的位置入栈 q.x++; q.y = 0;//转到下一行的行首 row++; } else//到了行尾 { q = result[result.size() - 1];//把上一行的坐标再拿出来 result.erase(result.end() - 1);//删除之,其实就是出栈的过程 row--; q.y++;//本行当前位置不合适,继续往后找一个合适的位置 } } for (auto i : result) cout << (i).x << " " << (i).y << endl; cout << "ok" << endl; }
4皇后,运行结果:
5皇后,运行结果:
6皇后,运行结果:
7皇后,运行结果:
8皇后,运行结果:
相关文章推荐
- N皇后问题的c++解法+java解法+python解法
- 同一问题的两种不同解法 : MFC8.0 与 C++ 标准库
- 背包问题的c++解法
- 一种便于理解的8皇后问题的回溯解法
- 谷歌2014年中国区应届毕业生校园招聘B轮机试第一题——数独问题的解法(C++实现)
- 皇后问题最快的解法(C语言)八皇后、十六皇后时间在毫秒级
- 对求解“皇后排列问题”的一个新解法!
- N皇后问题 位运算解法【JAVA实现】
- n皇后问题的非递归迭代算法(C++实现)
- C++递归问题之二——n皇后问题:以四、八皇后为例,给定n个皇后要求将它们放在一个n维矩阵中,任意两个皇后不能出现在同一行、列、主副对角线上,输出具体的摆放方式
- N皇后问题解法及解的个数
- C++实现 八皇后问题及其扩展N皇后问题(经典回溯算法)
- 字符串处理问题(c++和c#两种解法)
- 8皇后问题Python与C++实现
- 〖編程·C++〗回溯算法:排列树 - N皇后问题
- 用c++实现的8皇后问题
- N皇后问题的求解(C++代码)
- C++ 解决8皇后问题
- 八皇后问题的扩展,任意数量皇后问题的较快速解法
- n皇后问题的三种解法