算法分析 | 回溯算法设计之N后问题 C语言版

声明:凡代码问题,欢迎在评论区沟通。承蒙指正,一起成长!

目录

一、实验内容与要求

二、概要设计

三、直接上代码  

 四、运行结果


一、实验内容与要求

内容:(N后问题)在n*n格的棋盘上放置彼此不受攻击的n个皇后。按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。I后问题等价于在n*n格的棋盘上放置n个皇后,任何2个皇后不放在同一行或同一列或同一斜线上。
要求:随机输入正整数n,求出n后问题的解法个数,输出至少2种如图的形式的放置方案。

二、概要设计

 1.回溯法分析:解向量:(x1, x2, … , xn);显约束:xi=1,2, … ,n;隐约束:(1)不同列:xi、xj (2)不处于同一正、反对角线:|i-j|、|xi-xj|;
2.定义关于该问题的结构体类型queen,用于存储该问题的皇后数量(棋盘宽度)n、棋盘的每一行放置序列x[]和放置方案的解法个数sum;定义queen型全局变量X,初始化X的n、x[]、sum值;
3.主体算法:在算法迭代函数Backtrack()中,当k>0且k<X.n时,根据Place(k)中(|i-j|≠|xi-xj|)||(X.x[j]≠X.x[k]))的条件,以深度优先的方式迭代地对可行子树搜索,或剪去不可行子树,X.x[]记录解空间中结点信息,直到k=X.n时即搜索至叶结点,得到一个新的n皇后互不攻击放置方案,当前已找到的可行方案数sum自增1,函数PrintQueen(m)并打印当前方案下的棋盘矩阵(默认输出3种方案);
4.释放中间变量的内存,打印解法个数值sum。

三、直接上代码  

#include <stdio.h>
#include <stdlib.h>
typedef struct
{
    int n;
    int *x;
    long sum;
} queen;
queen X;
int Place(int k);//函数声明:根据可行性约束,减去不满足约束的子树;
void Backtrack(void);//函数声明:对整个解空间中回溯搜索;
void PrintQueen(int res);//函数声明:打印一次某方案的棋盘矩阵;
int main()
{
    int n,i;//初始化X
    printf("请输入皇后的数量n:");
    scanf("%d",&n);
    X.sum=0;
    X.n=n;// 皇后个数
    int *p;
    p=(int *)malloc(n*sizeof(int));
    for (i=1; i <= n; i++)
        p[i]= 0;
    X.x=p;
    Backtrack();
    free(p);
    printf("\n---%d后问题中共有%d种解法---\n",n,X.sum);
    return 0;
}
int Place(int k)//当前解
{
    int j;//当前已找到的可行方案数
    for (j=1; j<k; j++)
        if((abs(k-j)==abs(X.x[j]-X.x[k]))||(X.x[j]==X.x[k]))
            return 0;
    return 1;
}
void Backtrack(void)
{
    X.x[1]=0;
    int k=1,u=3,m=1;
    while(k>0)
    {
        X.x[k]+=1;
        while((X.x[k]<=X.n)&&!(Place(k)))
            X.x[k]+=1;
        if(X.x[k]<=X.n)
        {
            if(k==X.n)
            {
                if(m<=u)
                {
                    PrintQueen(m);
                    m++;
                    if(m==u+1)
                        printf("…………\n");
                }
                X.sum++;
            }
            else
            {
                k++;
                X.x[k]=0;
            }
        }
        else
            k--;
    }
}
void PrintQueen(int res)/* 打印棋局 */
{
    int i,j,N=X.n;
    printf("第%d种解法:\n", res);
    for (i = 1; i <= N; i ++)
    {
        for (j = 1; j <= N; j ++)
            if (j == X.x[i]) printf("  Q");
            else printf("  *");
        printf("\n");
    }
}
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

 四、运行结果

猜你喜欢

转载自blog.csdn.net/kndjg/article/details/123579904