回溯算法_八皇后问题的递归与非递归两种方法

回溯算法_八皇后问题的递归与非递归两种方法

问题描述

在8×8格的国际象棋上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。

解题思路

定义一个一维数组a[8],下标表示行数,值表示列数:a[行]=列

使用回溯算法,在第k行放置皇后时,逐列测试安全性,如果安全,在安全位置放置皇后,不安全,则继续测试下一行,即第k+1行

如果整行都无法放置,则返回k-1行,将a[k-1]移值下一列,重复测试

非递归方法

#include<iostream>
#include <cmath> 
using namespace std;

#define N 8
int a[N+1];

void show()
{
    for(int i = 1; i <= N; i++)
        cout << a[i] << " ";
    cout << endl;
}

// 对角线和列的约束条件
int check(int k) 
{
    for(int i = 1; i < k; i++)
        if(abs(a[i] - a[k]) == abs(i - k) || a[i] == a[k]) 
            return 0;
    return 1;
}

void backdata() 
{
    int k = 1;
    int count = 0;
    a[1] = 0;
    while(k > 0) 
    {
        a[k] += 1;
        while(a[k] <= N && check(k) == 0) // 第k个皇后的搜索位置
            a[k] += 1;
        if(a[k] <= N)
            if(k == N) // 找到一组解
            {
                show();
                count++;
            }
            else
            {
                k++; // 放置第下一个个皇后
                a[k] = 0; // 注意下一个皇后恢复至第一列
            }
        else k--; // 回溯
    }
    cout << "ans: " << count;
}

int main()
{
    backdata();
}

递归方法

#include<iostream>
#include <cmath> 
using namespace std;
 
#define N 8
 
int a[N], count=0;
 
void show()
{
    for(int i = 0; i <= N; i++)
        cout << a[i] << " ";
    cout << endl;
}
 
// 对角线和列的约束条件
int check(int k) 
{
    for(int i = 0; i < k; i++)
        if(abs(a[i] - a[k]) == abs(i - k) || a[i] == a[k]) 
            return 0;
    return 1;
}
 
void eight_queen(int n) // 递归回溯
{
    for(int i = 0; i < N; i++)
    {       
        a[n] = i; // 第k个皇后的搜索位置
        if(check(n))
        {           
            if(n == N - 1) // 找到一组解
            {
                show();
                count++;
            }         
            else
            {
                eight_queen(n + 1); // 放置第下一个个皇后
            }
        }
    }
}
 
int main()
{
    eight_queen(0); // 从第一行开始
    cout << count;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值