时间:2017.5.24
作者:夏晓林
问题描述:
编写一个程序exp3-6.cpp,求解皇后问题:在n×n的方格棋盘上,放置n个皇后,要求每个皇后不同行、不同列、不同左右对角线。
要求:(1)皇后的个数n由用户输入,其值不能超过20,输出所有的解。(2)采用类似于栈求解迷宫问题的方法。
原代码:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define MaxSize 100
typedef struct
{
int data[MaxSize]; //data[i]存放第i个皇后的列号
int top; //栈顶指针
} StType; //定义顺序栈类型
int count=0;
int place(StType st,int i,int j) //测试(i,j)是否与1~i-1皇后有冲突
{
int a=0; //a为函数的返回值
int k=1;
if (i==1)
{
a=1;
return a; //放第一个皇后时没有冲突
}
while (k<=i-1) //j=1到k-1是已放置了皇后的列
{
if ((st.data[k]==j)||(fabs(j-st.data[k])==fabs(i-k)))
{
a=0;
return a;
}
else
k++;
}
a=1;
return a;
}
void queen(int n) //求解n皇后问题
{
int i,j,k;
int find=0;
StType st; //定义栈st
st.top=0; //初始化栈顶指针
st.top++; //将(1,1)进栈
st.data[st.top]=1;
while (st.top>0) //栈不空时循环
{
i=st.top; //当前皇后为第i个皇后
if (st.top==n) //所有皇后均放好,输出一个解
{
printf("第%d个解:",++count);
for (k=1; k<=st.top; k++)
printf("(%d,%d) ",k,st.data[k]);
printf("\n");
}
find=0;
for (j=1; j<=n; j++)
if (place(st,i+1,j)) //在i+1行找到一个放皇后的位置(i+1,j)
{
st.top++;
st.data[st.top]=j;
find=1;
break;
}
if (find==0) //在i+1行找不到放皇后的位置,回溯
{
while (st.top>0)
{
if (st.data[st.top]==n) //本行没有可放位置,退栈
st.top--;
for (j=st.data[st.top]+1; j<=n; j++) //在本行找下一个位置
if (place(st,st.top,j))
{
st.data[st.top]=j;
break;
}
if (j>n) //当前皇后在本行没有可放的位置
st.top--; //退栈
else //本行找到一个位置后退出回溯
break;
}
}
}
}
int main()
{
int n;
printf(" 皇后问题(n<20) n=");
scanf("%d",&n);
printf(" %d皇后问题求解如下:\n",n);
queen(n);
printf("\n");
return 0;
}
结果展示:
学习心得:
通过栈来实现坐标的表示。采用回溯法来进行计算。