C语言编程中皇后问题回溯法的困惑~~

edward1992 2011-02-09 01:34:12
小弟我最近看C语言教材的时候看到了递归章节中的皇后问题:
在n*n个棋盘上放置n个皇后,这些皇后中任意两个皇后不能在同一行,同一列,同一条对角线上(包括主对角线和次对角线)。如果有解就输出所有合法的解。
我看懂了书上给的源代码,出于多思考多动手的原因(O(∩_∩)O哈哈~,精神可嘉吧?),我想把它改成用二维数组来做。但是我写出来的代码在编译过程就遇到很过错误了,想了好久都不明白,请各位高人们指点指点吧。让我趁机学习。
书上的源代码:
/* 文件名:s7_4.c, 皇后问题 */
/* 欢迎登陆C/C++教学网站:http://cs.scu.edu.cn/~youhongyao */

#include <stdio.h> /* 文件包含预处理命令,printf( )函数在其中声明 */
#include <stdlib.h> /* 文件包含预处理命令,system( )函数在其中声明 */

#define N 80 /* 皇后最多个数 */
#define FALSE 0
#define TRUE 1

void Queen(int n); /* n皇后问题 */
void TrySolution(int i,int n,int a[], int b[],int c[], int x[]); /* 回溯求解n皇后问题 */
void OutSolution(int n,int x[]);/* 输出一组解 */

int main(void) /* 主函数main(void) */
{
int n = 4;
Queen(n); /* 求解4皇后问题 */

system("PAUSE"); /* 调用库函数system() */
return 0; /* 返回值0 */
}

/* n皇后问题 */
void Queen(int n)
{
int a[N + 1], b[2 * N + 1], c[2 * N + 1]; /* a:某一列,b:副对角线,c:主对角线 */
int i, x[N + 1]; /* x:皇后所放置的列 */


/* 赋初值 */
for (i =1 ; i <= n; i++) a[i] = FALSE;
for (i = 1; i <= 2 * n; i++) b[i] = FALSE;
for (i = 1; i <= 2 * n; i++) c[i] = FALSE;

TrySolution(1, n, a, b, c, x); /* 递归求解n皇后问题 */
}

/* 前i-1个皇后已放置后,为第i个皇后选择合适的位置,a用于表示某列
是否放置有皇后,b表示某条副对角线是否放置有皇后,c表示某条主
对角线是否放置有皇后,x表示皇后所放置的列
*/
void TrySolution(int i, int n, int a[], int b[], int c[], int x[])
{
int j;
if ( i > n)
{ /* /i>n表示第1~n个皇后已放置好 */
OutSolution(n, x); /* 已得到解,输出解 */
}
else
{
for (j = 1; j <= n; j++)
{ /* 第i个皇后所放置的列 */
if(a[j]==FALSE&&b[i+j]==FALSE&&c[i-j+n]==FALSE)
{ /* 如果位置(i,j)所在的列,对角线没放置有皇后,
则在位置(i,j)放置第i个皇后
*/
a[j] = TRUE;
b[i + j]=TRUE;
c[i - j + n]=TRUE;
x[i] = j; /* 表示第i个皇后所放置的位置 */
TrySolution(i + 1, n, a, b, c, x); /* 再试探第i + 1个皇后所放置的位置 */
//释放位置(i,j),进行回溯
a[j] = FALSE;
b[i + j] = FALSE;
c[i - j + n] = FALSE;
}
}
}
}

/* 输出皇后问题的解 */
void OutSolution(int n,int x[])
{
int static num = 0; /* num表示当前已求得解的个数 */
int i;

printf("第%d个解:", ++num);
for(i = 1; i <= n; i++)
{ /* 输出解 */
printf("(%d,%d) ", i, x[i]);
}
printf("\n");
}


我的源代码:

#include <iostream>
using namespace std;

const int FALSE=0;
const int TRUE=1;
void Queen(int n);
void TrySolution(int i,int n,int *p);
void OutSolution(int *p,int n);
bool Row(int row,int *p,int n);

void main()
{
int n;
cout<<"Please enter a number:";
cin>>n;
int t=n+2;

int p[t][t];
int i,j;
for(i=0;i<n+2;i++)
{
for(j=0;j<n+2;j++)
*(*(p+i)+j)=FALSE;
}
TrySolution(2,n,p);
}

void TrySolution(int i,int n,int *p)
{
int j;
bool flag;
if(i>n)
{
OutSolution(n,p);
}
else
{
for(j=2;j<n+1;j++)
{
if((flag=Row(j,p,n))==TRUE&&*(*(p+i-1)+j-1)==FALSE&&
*(*(p+i+1)+j-1)==FALSE&&*(*(p+i-1)+j+1)==FALSE&&
*(*(p+i+1)+j+1)==FALSE)
{
*(*(p+i)+j)=TRUE;
}
TrySolution(i+1,n,p);
*(*(p+i)+j)=FALSE;
}
}
}

void OutSolution(int *p,int n)
{
static int num=0;
int i,j;

cout<<"The no."<<num<<" solution is:"<<endl;
for(i=2;i<n+1;i++)
{
for(j=2;j<n+1lj++)
{
cout<<*(*(p+i)+j)<<" ";
}
cout<<endl;
}
}

bool Row(int row,int *p,int n)
{
int i;
for(i=0;i<=n+2;i++)
{
if(*(*(p+i)+row)==TRUE)
return FALSE;
}
return TRUE;
}
...全文
288 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
edward1992 2011-05-02
  • 打赏
  • 举报
回复
结果发现好像没有解决到问题。~
logiciel 2011-02-17
  • 打赏
  • 举报
回复
(1)书上的源代码用专门的数组存放对角线,每个单元实际代表了多个点,因此只要判一个单元就够了.LZ改用二维数组后,则需要判断整条对角线,而以下代码只判断了当前点所在的对角线上周围的4个点,这是不够的:
if((flag=Row(j,p,n))==TRUE&&*(*(p+i-1)+j-1)==FALSE&&
*(*(p+i+1)+j-1)==FALSE&&*(*(p+i-1)+j+1)==FALSE&&
*(*(p+i+1)+j+1)==FALSE)
(2)LZ的下标范围使用有误;
(3)根据LZ程序中对二维数组的引用方式(*(*(p+i)+j)),应该用int **p定义二维数组,并为其分配内存.

#include <iostream>
using namespace std;

const int FALSE=0;
const int TRUE=1;
void Queen(int n);
/*
void TrySolution(int i,int n,int *p);
void OutSolution(int *p,int n);
bool Row(int row,int *p,int n);
*/
void TrySolution(int i,int n,int **p);
void OutSolution(int **p,int n);
bool Row(int row,int **p,int n);
bool Diag1(int column,int row,int **p,int n);//added
bool Diag2(int column,int row,int **p,int n);//added

void main()
{
int n;
cout<<"Please enter a number:";
cin>>n;
int t=n+2;

int **p;//int p[t][t];
int i,j;

p=new int *[t];//added
for(i=0;i<n+2;i++)
{
p[i]=new int[t];//added
for(j=0;j<n+2;j++)
*(*(p+i)+j)=FALSE;
}
TrySolution(1,n,p);//TrySolution(2,n,p);
}

void TrySolution(int i,int n,int **p)//void TrySolution(int i,int n,int *p)
{
int j;
//bool flag;
if(i>n)
{
OutSolution(p,n);//OutSolution(n,p);
}
else
{
for(j=1;j<=n;j++)//for(j=2;j<n+1;j++)
{
/*
if((flag=Row(j,p,n))==TRUE&&*(*(p+i-1)+j-1)==FALSE&&
*(*(p+i+1)+j-1)==FALSE&&*(*(p+i-1)+j+1)==FALSE&&
*(*(p+i+1)+j+1)==FALSE)
{
*(*(p+i)+j)=TRUE;
}
TrySolution(i+1,n,p);
*(*(p+i)+j)=FALSE;
*/
if(Row(j,p,n)&&Diag1(i,j,p,n)&&Diag2(i,j,p,n))
{
*(*(p+i)+j)=TRUE;
TrySolution(i+1,n,p);
*(*(p+i)+j)=FALSE;
}
}
}
}

void OutSolution(int **p,int n) //void OutSolution(int *p,int n)
{
static int num=0;
int i,j;

num++; //added
cout<<"The no."<<num<<" solution is:"<<endl;
for(i=1;i<=n;i++) //for(i=2;i<n+1;i++)
{
for(j=1;j<=n;j++) //for(j=2;j<n+1lj++)
{
cout<<*(*(p+i)+j)<<" ";
}
cout<<endl;
}
}

bool Row(int row,int **p,int n) //bool Row(int row,int *p,int n)
{
int i;
for(i=0;i<n;i++) //for(i=0;i<=n+2;i++)
{
if(*(*(p+i)+row)==TRUE)
return FALSE;
}
return TRUE;
}

//below are added
bool Diag1(int column,int row,int **p,int n)
{
int i;
int j;
for(i=column-1,j=row-1;i>0&&j>0;i--,j--)
{
if(*(*(p+i)+j)==TRUE)
return FALSE;
}
for(i=column+1,j=row+1;i<=n&&j<=n;i++,j++)
{
if(*(*(p+i)+j)==TRUE)
return FALSE;
}
return TRUE;
}

bool Diag2(int column,int row,int **p,int n)
{
int i;
int j;
for(i=column-1,j=row+1;i>0&&j<=n;i--,j++)
{
if(*(*(p+i)+j)==TRUE)
return FALSE;
}
for(i=column+1,j=row-1;i<=n&&j>0;i++,j--)
{
if(*(*(p+i)+j)==TRUE)
return FALSE;
}
return TRUE;
}
liuwu7517498 2011-02-13
  • 打赏
  • 举报
回复
又要顶起了,还是没大看明白
liuwu7517498 2011-02-13
  • 打赏
  • 举报
回复
楼主NB啊
edward1992 2011-02-13
  • 打赏
  • 举报
回复
又要顶起了,我还没明白哪。
edward1992 2011-02-13
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 liuwu7517498 的回复:]
楼主NB啊
[/Quote]
只是想学点东西嘛,没你说的那样。
edward1992 2011-02-12
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 wonder2008 的回复:]
你用二维的也没什么大的问题,只不过数组长度不固定就是你的不对了:
int p[t][t];
建议你也用以下来替换:
#define N 80 /* 皇后最多个数 */
int p[N][N];
[/Quote]
可是我看书的时候明明说数组长度是可以不确定的啊。
edward1992 2011-02-12
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 zhao4zhong1 的回复:]
“给定一个小点的输入,完整单步跟踪一遍。”是理解递归函数工作原理的不二法门!
[/Quote]
这我懂,但我现在的问题所在是对二维数组理解不到位不知道要怎么用二维数组的指针。
赵4老师 2011-02-12
  • 打赏
  • 举报
回复
“给定一个小点的输入,完整单步跟踪一遍。”是理解递归函数工作原理的不二法门!
竞天问 2011-02-11
  • 打赏
  • 举报
回复
多维(不是一维的都算)数组在定义时要求除最后一个维度外,其它维度必须是常量,要不就用new ,一维一维的申请
wonder2008 2011-02-11
  • 打赏
  • 举报
回复
你用二维的也没什么大的问题,只不过数组长度不固定就是你的不对了:
int p[t][t];
建议你也用以下来替换:
#define N 80 /* 皇后最多个数 */
int p[N][N];

33,311

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 新手乐园
社区管理员
  • 新手乐园社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧