八皇后问题 C++ 递归

最近在重新看递归,准备复试,刚好看到八皇后问题。

主要思路是画出8*8的棋盘,可放皇后位置为0,否则为1。因为正确解一定是每一行都有一个皇后,所以以行按深度优先搜索分解问题。从(0,0)开始放皇后,搜索下一行第一个0,放置皇后,相应不可放位置都置1,再在下一行搜索第一个0...如果遇到在第7行(从第0行开始)仍有0可以放皇后,则找到解;否则返回上一行,恢复棋盘,找该行第二个0放置皇后,继续往下搜索,多次返回后该行的所有0也都被搜索完毕,则再返回上一行进行类似搜索。

遇到的问题主要有两大方面:

1.循环实现放皇后对相应方格的置1操作,要注意循环条件,考虑4种情况。

2.递归中的循环逻辑。见代码注释。

另外,由于进入递归起始的位置是给定的(0,0),需要在主函数内循环实现对第0行所有位置的递归求解。这一点也是看了好久,通过递归层数计数才发现。

#include <iostream>
#include <stdio.h>

using namespace std;
//八皇后问题

int table[8][8] = {};
int count = 0;
typedef enum arg
{CLR,SET} ctr;
int countdg;//递归层数计数

void SetRowLineDiag(int x,int y,ctr arg);
void EightQ(int x,int y);
void copyArray(int (*array_temp)[8],int (*table)[8]); //数组指针
void coutArray(int (*array)[8]);

int main()
{
    int i;
    int array_temp[8][8]={};
    copyArray(array_temp,table);
    for(i=0;i<8;i++)
    {
        copyArray(table,array_temp);  //要注意返回后对棋盘的恢复
        EightQ(0,i);
    }

    cout<<count<<endl;
    return 0;
}

void SetRowLineDiag(int x,int y,ctr arg)  //x为行,y为列
/*皇后所在位置,相关位置置一或清零*/
{
    int i,j;
    for(i=0;i<8;i++)
    {
        table[i][y] = arg; //改列
        table[x][i] = arg; //改行
    }
    int s=x+y;
    if(s>=7)//左斜线
    {
        for(i=7;i>=s-7;i--)
        {
            j=s-i;
            table[i][j] = arg;
        }
    }
    else if(s<7)
    {
        for(j=0;j<=s;j++)
        {
            i=s-j;
            table[i][j] = arg;
        }
    }

    if(x>=y)//右斜线
    {
        for(i=x-y,j=0;i<=7;i++,j++)
            table[i][j] = arg;
    }
    else
    {
        for(j=y-x,i=0;j<=7;i++,j++)
            table[i][j] = arg;
    }
}

void copyArray(int (*array_temp)[8],int (*table)[8]) //数组指针
{
    int i,j;
    for(i=0;i<8;i++)
    {
        for(j=0;j<8;j++)
            array_temp[i][j] = table[i][j];
    }
}

void coutArray(int (*array)[8])//输出棋盘
{
    int i,j;
    for(i=0;i<8;i++)
    {
        for(j=0;j<8;j++)
            cout<<array[i][j];
        cout<<endl;
    }
    cout<<endl;
}

void EightQ(int x,int y) //逐行进行搜索
{
    if(x==7 && y<8)//得到解,计数加一
    {
        count++;
       // getchar();
        return ;
    }
    else if(y>=8)//已超边界,无解
        return ;

   // cout<<countdg++<<endl; //递归层数
    SetRowLineDiag(x,y,SET); //由上一层指定的该层皇后位置,相应位置置1
    int array_temp[8][8];
    copyArray(array_temp,table);//保存该层棋盘,即下一层初始棋盘
  //  coutArray(array_temp);
    int j=0;
    while(j<=7) //扫描下一层
    {
        while(table[x+1][j]==1 && j<8) //查找下一个为0可放皇后的位置
            j++;
        EightQ(x+1,j++);//这里一定要要注意j++,否则返回后j不变,不进入上一步的while里加1,会导致死循环
        copyArray(table,array_temp);//从下一层一个位置返回后,应对下一层的下一个位置进行求解,要恢复棋盘
      //  coutArray(table);
    }
    //cout<<countdg--<<endl;
    return ;
}

求解得92个解    



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值