N皇后问题---回溯法之一维数组存储

来源:互联网 发布:同城快送用什么软件 编辑:程序博客网 时间:2024/06/18 09:23

N皇后问题是一个经典的问题,在一个N*N的棋盘上放置N个皇后,每行一个并使其不能互相攻击(同一行、同一列、同一斜线上的皇后都会自动攻击)。

(注:本文采用一维数组存储棋盘,并利用特定性质解决皇后不冲突的问题,新手最好别看,先从二维数组开始学起,不然会很难受的。)

本题利用回溯法解决N皇后问题,其次,介绍memset的利弊(几乎花了一下午时间查bug,结果才知道是这里出问题了)

   本文大致思路:存储N个皇后到chessboard中,从i开始,每次找到一个可以放入的位置,若该位置不能放,回溯或者退出,若该位置是最后一个,则要输出这一种情况,count_num+1.最终结果即满足了条件

 

#include <iostream>#include <stdlib.h>#include <stdio.h>#include <string.h>//#include <limits.h>    //不是c++时INT_MAX的头文件是这个using namespace std;//a[i] == j即可确定该处可以有皇后int chessboard[10];int n;  //皇后数int chess(int row, int col){for(int i = 0; i < n; i++){       //i是每一行, a[i]是列,abs(row - i) == abs(col - a[i])即可满足对角线的重复,返回0即可if((chessboard[i] == col) || (abs(row - i) == abs(col - chessboard[i])))return 0;}return 1;}void print(){for(int i = 0; i < n; i++){for(int j = 0; j < n; j++){if(chessboard[i] != j)cout<<'.'<<" ";elsecout<<'#'<<" ";}cout<<endl;}for(int j = 0; j < n; j++)cout<<chessboard[j]<<" ";cout<<"-------------------------------------"<<endl;}void Queen(){int i = 0;int j = 0;int count_num = 0;while(i < n){//判断i行时能不能放Queenwhile(j < n){if(chess(i, j)){chessboard[i] = j;j = 0;break;       //不能再放Queen了}elsej++;}//一行下来没有放Queen的地方if(chessboard[i] == INT_MAX){if(i == 0)break;      //唯一跳出循环的位置else{//回溯,不可能没有位置放queeni--;j = chessboard[i] + 1;chessboard[i] = INT_MAX;continue;}}//最后一行也要回溯if(i == n - 1){print();count_num++;j = chessboard[i] + 1;chessboard[i] = INT_MAX;continue;}i++;}cout<<count_num<<endl;}void init(){int *p;for(p = chessboard; p < chessboard + n; p++)*p = INT_MAX;}int main(){    scanf("%d", &n);    init();//    memset(chessboard, INT_MAX, sizeof(chessboard));   //初始化棋盘    Queen();    return 0;}

  小结:读者可先利用chessboard[0][0]来测一下,就会理解很多了,其次,chessboard[]中存储的是路径.

深入挖掘N皇后:N皇后文字详解  但是和我代码差不多,个人感觉不好理解,还不如直接看代码好一点

最后温馨提醒,别用INT_MAX 初始化数组,初始化0没问题,但是如果你你按照我main函数中的memset函数就会出错,具体看链接memset常见错误


原创粉丝点击