多种解法解决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 20+7
using namespace std;

int y_pos[maxsize];
int n;
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;
}

void show()
{
    printf("\nThe %d number position:\n",count);
    for(int i=0;i<n;i++)
    {
        printf("\t(%d,%d)",i,y_pos[i]);
    }
}
void RecurBack(int num)
{
    if(num==n)
    {
        count++;
        show();
        return;
    }
    for(int i=0;i<n;i++)
    {
        y_pos[num]=i;
        if(judge(num))
        {
            RecurBack(num+1);
        }
    }
}
int main()
{
    printf("input n:\n");
    scanf("%d",&n);
    memset(y_pos,0,sizeof(y_pos));
    RecurBack(0);
    printf("\ncount:%d",count);
    return 0;
}

思路就是: 直接从不同行开始选取,然后判断是否满足条件。思路主要就是以皇后的个数作为行数,然后递归下去,递归出口就是回溯

0x5 全排列解法

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#define maxsize 20+7
using namespace std;

int queen[maxsize];
int n;
int count_=0;
int main()
{
    printf("input n:\n");
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        // Init array
        queen[i]=i;
    }
    do
    {
        /*
        for(int i=0;i<n;i++)
            printf("%d\t",queen[i]);
        printf("\n");
        */
        // generate the permutation of queen
        bool find=true;
        for(int i=0;i<n;i++)
        {
            for(int j=i+1;j<n;j++)
            {
                if(j-i==abs(queen[j]-queen[i]))
                {
                    //cout<< "false!!! " <<endl;
                    find=false;
                    break;
                }
                if(!find)
                    break;
            }
        }
        //printf("\n");
        if(find)
        {
            count_++;
        }
    }while(next_permutation(queen,queen+n));
    printf("count:%d",count_);
    return 0;
}

这个可以来说也很好,都是暴力解法,时间差别主要是在生成全排列的过程,但是这个解法可以利用STL,代码可以说是相当简洁的了。

0x6 用栈解决

​ 用栈来模拟递归过程,这个是我数据结构的一个作业。

#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;
}

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