使用迭代法解决皇后问题

来源:互联网 发布:2017淘宝运营助理面试 编辑:程序博客网 时间:2024/05/10 11:06
解决此皇后问题可以有很多方法,如回溯法、迭代法等;一般我们见过的都是基于回溯解决皇后问题的,而这次是使用迭代解决的,相比回溯,迭代会复杂的多。
源代码如下:(核心就是保存中间结点及处理)
 
#include"iostream"
#include"math.h"
int Y[16];//利用一维数组记录已占的列号
int sum=0;//可行解个数
struct Node//记录皇后level进行到col列
{
 int level;
 int col;
};
Node node[1000];
int top=0;//模拟栈,元素个数
int Operation(int n);
int main()
{
 int n;
 scanf("%d",&n);
 int k=Operation(n);
 printf("%d\n",k);
 system("pause");
 return 0;
}
int Placed(int t)//对皇后t放在record[t]列做判断
{
 int i;
 for(i=1;i<=t-1;i++)
  if(Y[i]==Y[t] || abs(t-i)==abs(Y[t]-Y[i]))//判断是否同列及对角
   return 1;
 return 0;
}
////迭代法,关键是需要记录空间中的各个节点
int Operation(int n)//
{
 int i,j,k,flag=0;
 int t=1;//记录已经放置皇后的个数
 i=1;
 while(i<=n)//(1)默认从第一个皇后开始放置,依次尝试i列,即尝试1至n列
 {
  t=1;
  Y[t]=i;//记录皇后t放置的列号
  top++;
  node[top].level=t;//保存这个空间节点
  node[top].col=i;
  t++;;
  j=1;//下一个皇后从第j列开始尝试放置
  while(t<=n)//(2)处理第2到第t个皇后
  {
   flag=0;//判断这个皇后能否放置成功
   //***************
   while(j<=n)//(3)放置第t个皇后第j列
   {
    Y[t]=j;
    if(!Placed(t))//放置成功,然后放下一行
    {
     flag=1;//皇后t放置成功,
     //放置成功时生成一个新节点
     top++;
     node[top].level=t;
     node[top].col=j;
     //放置成功,然后放下一行
     t++;
     j=1;//注意初始化
     break;//结束本次循环(即本行的放置),转至循环(2)进行下一个皇后放置的处理
    }
    //若放置不成功,对皇后t进行下一列放置探测
    else
     j++;
   }///
   //**************
   //皇后t尝试所有列都失败,
   if(flag==0)//结束本行放置,回溯到皇后(t-1)的下一列,这是通过删除一个节点实现
   {
    if(top==0)////(位置1)对于元素个数,在减小时,一定要保证不能小于0!实际这时top最小为1,不会执行这句,这里只是起注释作用
     printf("top==%d!",top);
    t=node[top].level;
    j=node[top].col+1;
    top--;              //立刻去除此死节点
    if(j>n)
    {
     t=node[top].level;
     j=node[top].col+1;
     top--;
     ////在位置1处top可能为1时,那么此时top经过两次自减已经变为-1,所以一定要对这种情况进行判断,防止出现元素个数top<0情况
     if(top<0)
     {
      //printf("t=%d,top=%d\n",t,top);
      break;
     }
    }
    //当回溯到第一层,就应该跳出第二层while循环(第二层循环是处理2--n层的)
    if(t==1)
     break;
   }
   else if(t>n)//找到一种方案,放置成功
   {
    sum++;
    for(k=1;k<=n;k++)
     printf("%d ",Y[k]);
    printf("\n");
    //对同层的下一列进行搜索
    t=node[top].level;//此时也是t=n;
    j=node[top].col+1;
    top--;
    if(j>n)//当同层所有列已搜索,则对上层的下一列进行搜索
    {
     t=node[top].level;
     j=node[top].col+1;
     top--;
    }
   }
  }//2.while
  i++;//对第一个皇后进行下一列尝试
  //printf("跳出第二层循环!\n");
 }//1.while
 
 return sum;
}