对求解“皇后排列问题”的一个新解法!

 /*对求解“皇后排列问题”的一个新解法,在程序中是对于一个虚拟的数组进行的操作,并没有实际使用数组,唯一用的数组就是记录有效点的数组,大小不会超过最大的列值,虽然程序分了几个子程序,但是实际的运行效率比普通的算法快一些,有兴趣就看看代码吧

另外,我一直在想,对于任意指定的行列值,“皇后问题”的解的个数是一定的,但是解的个数怎么求呢?

有没有高手把求解的思路说一下,我在这先谢了

*/

//**********************************************************

//**********************************************************

//指定行列数,求解皇后问题的答案

 

   //这里采用的是对虚拟数组的遍历

   //步骤:

   //1:逐列扫描

   //2:查找前面的点是否存在有冲突的值

   //3:无冲突则继续扫描下一行,有冲突则回溯扫描前一行

   //4:最后一列,扫描到符合要求的点就打印问题解决的排列

   //5: 继续扫描(或者回溯扫描)

   /*

    * 算法描述:

    * 采用一个数组ary存放已经扫描过的有用的点值

    * 采用IsConfilct函数对当前扫描的点进行有效性判断

    * 如果当前扫描的点有效则保存进ary,否则继续扫描

    */

 
#include <iostream>
#include <cstddef>

 

//定义一个点的结构

//仅用于记录行列的索引,所以x,y 不会小于0

typedef struct Point

{

   size_t x;

   size_t y;

   Point(){}

   Point(size_t ix, size_t iy) : x(ix), y(iy) {}

   bool operator==(const Point& pt) const

   {

      return (x==pt.x && y==pt.y);

   }

};

 

//IsConflict():用于检查ptAry中是否存在与curPoint有冲突的点,存在返回true,不存在返回false

//参数:curPoint当前用于判断的点

//ptAry, 保存有效点用的数组

// n, 数组ptAry中有效点的个数

 

bool IsConflict(const Point& curPoint, Point* ptAry, size_t n)

{

   for(size_t i=0; i<n; i++)

   {

      //判断冲突点的条件 //存在同行的元素

      int stepy = ptAry[i].x - curPoint.x;

      size_t testy = ptAry[i].y +  abs(stepy);

      if((curPoint.x == ptAry[i].x) || (curPoint.y == testy)) //存在斜线上的元素

      { return true; }

   }

   return false;  

}

 

void PrintSuccess(const Point* ptAry, size_t MaxCol)

{

   static int ifound = 0;

   ifound++;

   cout << "This is the " << ifound << " QueenSearch solution" <<  endl;

   for(size_t i=0; i<MaxCol; i++)

   {

      cout <<"x: " << ptAry[i].x << ", y: " << ptAry[i].y << endl;

   }

   cout << endl;

}

 

//seek()用于递归扫描列中点的函数,并将有效点记录进ptAry

/*参数

 * curCol,输入当前欲扫描的列值

 * ptAry 记录有效点用的数组

 * MaxRow, 最大有效行数

 * MaxCol, 最大有效列数

 */

void seek(size_t curCol, Point* ptAry, size_t MaxRow, size_t MaxCol)

{

   if(curCol == MaxCol) return;      //超越边界

  

   for(size_t i=0; i<MaxRow; i++)

   {

      Point curPt(i, curCol);

      if(!IsConflict(curPt, ptAry, curCol)) //前面不存在有冲突的点,继续递归扫描

      {

         //保存有效点,继续扫描下一列

         ptAry[curCol] = curPt;

         seek(curCol+1, ptAry, MaxRow, MaxCol);

         //如果当前扫描的列是最后列则打印有效点数组

         if(curCol == MaxCol-1)

         {

            PrintSuccess(ptAry, MaxCol);

         }       

      }

     

      //如果当前扫描的点不合要求,则继续扫描下一个点    

   } 

}

 

//MaxRow 指定问题求解的最大行数

//MaxCol 指定问题求解的的最大列数

void QueenSearch(size_t MaxRow, size_t MaxCol)

{

   Point* ptAry = new Point [MaxCol]; //保存有效点用的数组

   seek(0, ptAry, MaxRow, MaxCol);      //查询有效点    

   delete[] ptAry;

}

 

//********************************************************

 

int main( void )

{

   QueenSearch(10,10);

 

   cout << "over" << endl;

   char x;

   while( x =cin.get(),x!='#')

   return 0;

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值