八皇后问题(减支思想、全列举)

来源:互联网 发布:自学编程应该看什么书 编辑:程序博客网 时间:2024/04/28 20:25

八皇后问题描述:

给出n*n的棋盘,在上面摆放n个棋子,每个棋子在棋盘上不能处于同一行列或对角线上。

举个n=4的例子:

如图就是n=4时符合情况的一种情况。

解决思想:

1.减支思想:

通过分析减少不必要的暴力搜索降低算法地复杂度

①、共有n*n个格子,需摆放n个棋子,就是说考虑不同行摆放的话会有n^n种情况;

②、再考虑也不能同列的情况,会有n!种情况。

2.信息浓缩:

通过适当的表示方法减少编程的复杂度(其实就是选择合适的数据结构)

这道题可以考虑使用数字记录棋子在该行的位置,比如上图可以考虑记录为(2,4,1,3)

难点:

思想比较简单,主要是全列举有点难。

全列举就是把减支思想提到n!种情况全部列举出来。

解决办法:通过递归。

图片是一部分过程,每个done!!!!表示一次列举完成,可以看到,思想是将1,2,3,4几个数字依次放入数组中。一次举例完成后,某一数字后移一位,比如第二次就是1,2不动,3后移一位,4填补上空缺。接下来是1不动,2后移一位,3,4填不上空缺。

最后检测是否满足条件比较简单,直接上代码。

之所以记录下来是因为全列举对我来说还需要列举,空手写递归的能力不是很足,写递归的时候有好多细节会遗漏。

#include <cstring>#include "stdafx.h"#include <iostream>#include <windows.h>using namespace std;int n = 0; //棋盘行列数void check_map(int* map){//检查棋盘(正反向对角线不相撞)for (int i = 0; i < n; i++){for (int j = i + 1; j < n; j++)if (map[i] - map[j] == i - j || map[i] - map[j] == j - i)return;}for (int i = 0; i < n; i++)cout << map[i] << " ";cout << endl;}void set_map(int start, int count, int* map){for (int i = 0; i < n; i++)//将不比count小的数置0{if (map[i] >= count)map[i] = 0;}//check_map(map);//观察列举的过程if (count == n)//若count已经是最后一位数,则只放入并检测{for (int i = start; i < n; i++){if (map[i] == 0){map[i] = count;break;}}//Sleep(1000);check_map(map);//cout << "done!!!!" << endl;return;}if (count < n)//若count不是最后一位,则放入数据之后调用set_num(0,count+1),然后调用set_num(start+1,count){for (int i = start; i <= n; i++){if (map[i] == 0){map[i] = count;start = i;//更新一下startbreak;}if (n == i)//若后面的位置都被占了,说明举例完成,直接退出return;}set_map(0, count + 1,map);//从位置0开始寻找可以放入的位置if(start+1<n)set_map(start + 1, count,map);//尝试下一个可以放入的位置*/}}int main(void){cin >> n;int* map = new int[n];memset(map, 0, n * sizeof(int));set_map(0, 1, map);cin >> n;return 0;}



0 0
原创粉丝点击