八皇后问题——枚举法,回溯法

问题描述

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

枚举法

别的不说了,直接上代码

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

void print_(int qu[])        //输出显示函数
{
    int i, j;
    for(i = 0; i < 8; i++){
        for(j = 0; j < qu[i]; j++){
            printf("%c", 6);
        }
        printf("%c", 12);
        for(j = 0; j < 8-qu[i]-1; j++){
            printf("%c", 6);
        }
        printf("\n");
    }
}

bool is(int qu[])              //判断是否会冲突
{
    int i, j;
    for(i = 0; i < 8; i++)
    {
        for(j = 0; j < i; j++)
        {
            if(qu[i] == qu[j]) return false;
            if(abs(qu[i]-qu[j]) == abs(i-j)) return false;
        }
    }
    return true;
}

int main()
{
    int a[10]={0};
    int i, number = 1;
    for(a[0] = 0; a[0] < 8; a[0]++)     //依次枚举8行。。。
    for(a[1] = 0; a[1] < 8; a[1]++)
    for(a[2] = 0; a[2] < 8; a[2]++)
    for(a[3] = 0; a[3] < 8; a[3]++)
    for(a[4] = 0; a[4] < 8; a[4]++)
    for(a[5] = 0; a[5] < 8; a[5]++)
    for(a[6] = 0; a[6] < 8; a[6]++)
    for(a[7] = 0; a[7] < 8; a[7]++)
    {
        if(is(a)){
            printf("Kase %d:\n", number++);
            print_(a);
            printf("\n");
        }
    }
    return 0;
}

回溯法

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

void showQueen(int queenArr[], int n, int nSolution)    //输出显示函数
{
    printf("Case %d:\n", nSolution);
    for(int i = 0; i < n; i++){
        for(int j = 0; j < queenArr[i]; j++){
            printf("%c", 6);
        }
        printf("%c", 12);
        for(int j = 0; j < n - queenArr[i] - 1; j++){
            printf("%c", 6);
        }
        printf("\n");
    }
}

bool isClash(int queenArr[], int nRow)
{
    for(int iRow = 0; iRow < nRow; iRow++){          ///检测当前第nRow行的摆放是否与其前面第iRow行冲突
        if(queenArr[iRow] == queenArr[nRow]){           ///在同一列上,冲突
            return true;
        }
        if(abs(queenArr[iRow]-queenArr[nRow]) == abs(iRow-nRow)){  ///在对角线上,冲突
            return true;
        }
    }
    return false;
}

void putQueen(int queenArr[], int nRow, int nLen, int &nSolution)  ///已放完前nRow行的皇后,正在放第nRow行的皇后
{
    for(int i = 0; i < nLen; i++){
        queenArr[nRow] = i;                                    ///把皇后放在第nRow行的第i列
        ///检查冲突,如果有冲突,忽略从第nRow行开始以下的所有皇后摆放
        if(!isClash(queenArr, nRow)){
            if(nRow == nLen - 1){   ///全部8行已经摆放完毕,且无冲突
                nSolution++;
                showQueen(queenArr, nLen, nSolution);
            }
            else{
                putQueen(queenArr, nRow + 1, nLen, nSolution);  ///放下一行皇后的位置
            }
        }
    }
}

int main()
{
    int queenArr[20];
    int nSolution = 0;           ///解法数量
    putQueen(queenArr, 0, 8, nSolution);   ///从第0行开始放,8皇后问题
    return 0;
}

但在有些问题中,回溯法常常会产生大量的重复计算,导致TLE,可用动态规划来解决。。。

    原文作者:八皇后问题
    原文地址: https://blog.csdn.net/fenoix/article/details/77351604
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞