第三次数据结构上机

该博客介绍了利用回溯法解决皇后问题的C语言程序设计。实验要求在n×n棋盘上放置n个皇后,确保它们不在同一行、列或对角线上。程序通过栈来模拟解题过程,当无法放置皇后时进行回溯。实验中包含了回溯思路、算法设计、函数说明,并提供了输入输出示例。

实验题目

编写一个程序exp3-6.cpp,求解皇后问题:在n×n的方格棋盘上,放置n个皇后,要求每个皇后不同行、不同列、不同左右对角线。

要求:(1)皇后的个数n由用户输入,其值不能超过20,输出所有的解。(2)采用类似于栈求解迷宫问题的方法。

实验步骤

(包括基本设计思路、算法设计、函数相关说明、输入与输出以及程序运行结果)

基本设计思路:回朔思想。

算法设计:定义一个栈sqstack,用于表示皇后棋盘的行数,定义一个一维数组向x[]=0,用于存储棋盘中的列数(一维数组可以直接防止皇后同行),每到一行,取栈顶元素e,x[e]++;然后判断是否能放皇后,行则入栈一次,接着再次取栈顶元素,x[e]归零,不行则x[e]++,直至x[e]增加加到n。如果该行都不能放皇后,则出栈一次,接着取栈顶元素,继续上述过程。最后栈空时退出。

函数相关说明:void queens(int *x,intn,sqstack *&s);//进行回朔的过程

int judge(int *x,int k);//判断是否能放皇后

//只要有某行(第i行)皇后与这个第k行的皇后处在同一列(x[i]=x[k])或者处在同一斜线(|i-k|=|x[i]-x[k]|),则立即返回假(0)

void print(int *x,int n);//打印结果函数

void initstack(sqstack*&s);//初始化栈,其中,将栈数据项全部赋值为1,2...20

void push(sqstack *&s);//进栈

void pop(sqstack *&s);//出栈

void gettop(sqstack *s,int&e);//取栈顶元素

bool stackempty(sqstack *s);判断栈是否为空

输入:4,5,10

输出:见运行图。

运行结果:




实验心得体会

通过这次实验,复习了回朔的解题方法,以及如何用栈解决问题,进一步熟悉了栈的使用。

源程序清单(代码)

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <malloc.h>

using namespace std;

typedef struct
{
    int k[21];
    int top;
} sqstack;

void queens(int *x,int n,sqstack *&s);
int judge(int *x,int k);
void print(int *x,int n);
void initstack(sqstack *&s);
void push(sqstack *&s);
void pop(sqstack *&s);
void gettop(sqstack *s,int &e);
bool stackempty(sqstack *s);

int main()
{
    sqstack *s;
    int n;
    int *x;
    initstack(s);
    scanf("%d",&n);
    x=(int *)malloc(sizeof(int)*(n+1));
    queens(x,n,s);
    return 0;
}
int judge(int *x,int k)
{
    int i;
    for(i=1; i<k; i++)
    {
        if((x[i]==x[k])||(fabs(x[i]-x[k])==fabs(i-k)))
            return 0;
    }
    return 1;
}
void queens(int *x,int n,sqstack *&s)
{
    int e,i=1;
    push(s);
    gettop(s,e);//进栈一次
    x[e]=0;
    while(!stackempty(s))//栈不为空
    {
        x[e]++;
        while(x[e]<=n&&!judge(x,e))
            x[e]++;
        if(x[e]<=n)
        {
            if(e==n)
                {
                    printf("第%d个解:",i);
                    print(x,e);
                    i++;}
            else
            {
                push(s);
                gettop(s,e);//进栈
                x[e]=0;
            }
        }
        else
        {
            pop(s);
            gettop(s,e);//出栈
        }
    }
}
void print(int *x,int n)
{
    int i;
    for(i=1; i<=n; i++)
    {
        if(i==n)
            printf("%d",x[i]);
        else
            printf("%d ",x[i]);
    }
    printf("\n");
}
void initstack(sqstack *&s)
{
    s=(sqstack *)malloc(sizeof(sqstack));
    int i;
    for(i=0; i<21; i++)
        s->k[i]=i+1;

    s->top=-1;
}
void push(sqstack *&s)
{
    s->top++;
}
void pop(sqstack *&s)
{
    s->top--;
}
void gettop(sqstack *s,int &e)
{
    e=s->k[s->top];
}
bool stackempty(sqstack *s)
{
    return(s->top==-1);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值