数据结构学习之栈求解n皇后问题

数据结构学习之栈求解n皇后问题

0x1 目的

​ 深入掌握栈应用的算法和设计

0x2 内容

​ 编写一个程序exp3-8.cpp求解n皇后问题。

0x3 问题描述

即在n×n的方格棋盘上,放置n个皇后,要求每个皇后不同行、不同列、不同左右对角线。

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

0x4 代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <string.h>
#define MaxSize 100000+7
#define maxsize 20+7
using namespace std;

int path[maxsize][maxsize];
int n;

int y_pos[maxsize];
int count=0;
bool judge(int num)
{
    for(int i=0;i<num;i++)
    {
        if(y_pos[i]==y_pos[num] || abs(y_pos[num]-y_pos[i])==num-i)
            return false;
    }
    return true;
}
typedef struct
{
    int x;
    int y;
    int di;
}Box;

typedef struct
{
    Box data[MaxSize];
    int top;
}StType;

void InitStack(StType *&s)
{
    s=(StType *)malloc(sizeof(StType));
    s->top=-1;
}

void DestroyStack(StType *&s)
{
    free(s);
}

bool GetTop(StType *&s,Box &e)
{
    if(s->top==-1)
        return false;
    e=s->data[s->top];
    return true;
}

bool push(StType *&s,Box e)
{
    if(s->top==MaxSize-1)
        return false;
    s->top++;
    s->data[s->top]=e;
    return true;
}

bool pop(StType *&s,Box &e)
{
    if(s->top==-1)
        return false;
    e=s->data[s->top];
    s->top--;
    return true;
}

int GetLength(StType *s)
{
    return(s->top+1);
}

bool EmptyStack(StType *s)
{
    return(s->top==-1);
}



void SetPath(int ex,int ey,int k)
{
    int xi=ex;
    int yi=ey;
    for(int i=0;i<n;i++)
    {
        path[xi][i]+=k;
        path[i][yi]+=k;
    }
    int x1,x2,y1,y2;
    x1=x2=xi;
    y1=y2=yi;
    while(x1>0&&y1>0)
        path[--x1][--y1]+=k;
    while(x2<n&&y2<n)
        path[x2++][y2++]+=k;
    path[xi][yi]-=k*2;
}

void printSolution()
{
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            if(y_pos[i]==j)
                printf("q");
            else
                printf("*");

        }
        printf("\n");
    }
    printf("\n");
}

void Disp(StType *s)
{
    for(int i=0;i<s->top;i++)
        printf("\t(%d,%d)",s->data[i].x,s->data[i].y);
}

void SolveQ(int n)
{
    int x1,y1,di;
    StType *st;
    InitStack(st);
    Box e;
    e.x=0;
    e.y=-1;
    push(st,e);
    while(!EmptyStack(st))
    {
        GetTop(st,e);
        x1=e.x;
        y1=e.y;
        bool find=false;
        if(x1==n)
        {
            printSolution();
            Disp(st);
            printf("\n");
            count++;
        }
        while(y1<n-1 && !find)
        {
            y1++;
            y_pos[x1]=y1;
            st->data[st->top].y=y1;
            if(judge(x1))
            {
                find=true;
                e.x=x1+1;
                e.y=-1;
                push(st,e);
            }
        }
        if(!find)
        {
            pop(st,e);
        }
        //pop(st,e);
    }
}


int main()
{
    printf("please input n:\n");
    scanf("%d",&n);
    memset(path,0,sizeof(path));
    memset(y_pos,0,sizeof(y_pos));
    SolveQ(n);
    printf("\n count:%d \n",count);
    return 0;
}


0x5 结果

image-20190412092903446

0x6 总结

​ 当时我在写的时候很纠结从0开始的问题,思想肯定是这样子的,先遍历每一行的每一列,然后在回溯。那么就需要做好回溯的标志e.x记录当前在第几行,方便下次回溯到e.x-1,这里唯一需要注意的是判断打印条件,if(x1==n),一开始我以为既然已经让第七行进栈了,那么说明满足,但是后面我理解错了,程序的逻辑是下一行进栈开始的时候y1=-1的,也就是我们要去到第8行才能知道第7行的结果是可以的。

posted @ 2019-04-12 09:39  xq17  阅读(1435)  评论(0编辑  收藏  举报