多种解法解决n皇后问题

时间:2023-03-09 00:25:25
多种解法解决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;
}