我的课后作业:N皇后问题


“八皇后问题”是算法与数据结构中的经典问题,是回溯算法的代表,也是栈的重要应用。不懂什么是“八皇后”?SEE THIS


N皇后问题是更普遍情况下的情况。这里给出我用C++实现的N皇后算法。


1.头文件stack.h

#ifndef _STACK_H_
#define _STACK_H_
#include "Vector.h" //以向量为基类
template <typename T> class Stack: public Vector<T> { //由向量派生的栈模板类
public: //size()、empty()以及其它开放接口均可直接沿用
   void push(T const & e) { Insert(Size(), e); } //入栈
   T pop() { return Remove(Size()-1); } //出栈
   T& top() { return (*this)[Size()-1]; } //取顶
};
#endif


2.头文件queen.h

#ifndef _QUEEN_H_
#define _QUEEN_H_
//代码4.12   
struct Queen { //皇后类
   int x, y; //皇后在棋盘上的位置座标
   Queen(int xx = 0, int yy = 0) : x(xx), y(yy) {};
   bool operator==(Queen const & q) { //重载判等操作符,以检测不同皇后之间可能的冲突
      return    (x == q.x) //行冲突(这一情况其实并不会发生,可省略)
             || (y == q.y) //列冲突
             || (x + y == q.x + q.y) //沿正对角线冲突
             || (x - y == q.x - q.y); //沿反对角线冲突
   }
   bool operator!=(Queen const & q) { return !(*this == q); } //重载不等操作符 /*DSA*/可否写成:return *this != q?
};
#endif

3.主程序main.cpp

#include <iostream>
using namespace std;
#include <stdio.h>
#include <stdlib.h>
#include "stack.h" //栈
#include "queen.h" //引入皇后类
typedef enum {Continuous, Step} RunMode;
RunMode runMode; //运行模式
int nSolu=0; //解的总数
int nCheck=0; //尝试的总次数
int count=0;//一个计数变量
int N = 0; //棋盘大小
FILE *file;//文件指针
#define QUEEN_MAX 20 //皇后最大数量
void placeQueens(int);
void displayRow(Queen& q, int);
void displayProgress(Stack<Queen>& S, int);
void printinfile(Queen& q);
/******************************************************************************************
 * n皇后(迭代版)
 ******************************************************************************************/
int main() {
   int start=0,nQueen=0;
   cout<<"*************N皇后问题求解程序**************"<<endl<<endl;
   cout<<"输入问题的规模,N= ";
   cin>>nQueen;
   N=nQueen;
   cout<<endl<<"请选择:单步演示(输入1)还是查看结果(输入2) ";
   cin>>start;
   if(start==1) runMode=Step;
   else runMode=Continuous;
   placeQueens(nQueen); //启动查找
   cout  << endl << nSolu << " solution(s) found after "
         << nCheck << " check(s) for "
         << nQueen << " queen(s)\n" << endl ; //输出解的总数
   return 0;
}
/********************************具体函数的实现******************************************/
void displayRow(Queen& q) { //打印当前皇后(放置于col列)所在行
   printf("%2d: ", q.x);
   int i = 0;
   while (i++ < q.y) printf("[]");
   printf("█");
   while (i++ < N) printf("[]");
   printf("%2d\n", q.y);
}
void displayProgress(Stack<Queen>& S, int nQueen) { //在棋盘上显示搜查的进展
   system("cls");
   N = nQueen; S.Traverse(displayRow);
   if (nQueen <= S.Size())
      cout  << nSolu << " solution(s) found after " << nCheck << " check(s)\a";
   getchar();
}
void printinfile(Queen& q)//在文件中打印结果
{
    file=fopen("result.txt","a+");//创建文件存储结果
    fprintf(file,"%2d: ",q.x);
    int i=0;
    while(i++ <q.y) fprintf(file,"[]");
    fprintf(file,"█");
    while(i++<N) fprintf(file,"[]");
    fprintf(file,"%2d\n",q.y);
    count++;
    if(count>=N)//完整打印出一个解后,打印分隔
    {
        fprintf(file,"这是第%d个解-----------\n",nSolu);
        count=0;
    }
    fclose(file);
}
    //代码4.13
void placeQueens(int N) { //N皇后算法(迭代版):采用试探/回溯的策略,借助栈记录查找的结果
   unlink("result.txt");//更新存储文件
   Stack<Queen> solu; //存放(部分)解的栈
   Queen q(0, 0); //从原点位置出发
   do { //反复试探、回溯
      if (N <= solu.Size() || N <= q.y) { //若已出界,则
         q = solu.pop(); q.y++; //回溯一行,并继续试探下一列
      } else { //否则,试探下一行
         while ((q.y < N) && (0 <= solu.Find(q))) //通过与已有皇后的比对
            { q.y++; nCheck++; } //尝试找到可摆放下一皇后的列
         if (N > q.y) { //若存在可摆放的列,则
            solu.push(q); //摆上当前皇后,并
            if (N <= solu.Size()) nSolu++; //若部分解已成为全局解,则通过全局变量nSolu计数
            q.x++; q.y = 0; //转入下一行,从第0列开始,试探下一皇后
         }
      }/*DSA*/
      /*选择的方式不同,选择不同的函数*/
      if (Step == runMode) displayProgress(solu, N);
      else
      {
            if(N<=solu.Size())
                solu.Traverse(printinfile);
      }
   } while ((0 < q.x) || (q.y < N)); //所有分支均已或穷举或剪枝之后,算法结束
}
/************************************************************************************/


运行结果:


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章