八皇后java非递归_八皇后的递归与非递归解

1、递归。递归真是个好东西,解法一目了然。

#include

#define N 8

int l[14];

int r[14];

int q[N];

int col[N];

static int cnt = 0;

void try(int i)

{

int j;

for(j=0; j

{

if(l[i+j] == 0 && r[i-j+7] ==0 && col[j] == 0)

{

l[i+j]=1;

r[i-j+7] =1;

col[j] = 1;

q[i] = j;

if(i+1 == N)

{

++cnt;

//    return;

}

else

{

try(i+1);

}

l[i+j] = 0;

r[i-j+7] = 0;

col[j] = 0;

q[i] = -1;

}

}

}

int main()

{

int i;

for(i=0; i<14; i++)

{

l[i] = 0;

r[i] = 0;

}

for(i = 0; i

{

col[i] = 0;

q[i] = -1;

}

try(0);

printf("cnt = %d\n", cnt);

return 0;

}

2、非递归解

#include

#define QUEEN 8 //皇后数量

int queen[QUEEN] ; //下标代表所在列号,值代表所在行号,

//如queen[1]=2表示第1列第2行有个皇后

bool col_YN[QUEEN] ;      //棋局的每一行是否有棋,有则为1,无为0 ;

bool passive_YN[2*QUEEN-1] ; //斜率为1的斜线方向上是否有棋,共有2*QUEEN-1个斜线

bool negative_YN[2*QUEEN-1] ; //斜率为负1的斜线方向上是否有棋

//用全局变量,因全局数组元素值自动为0

int main()

{

int col = 0 ;//游标,当前移动的棋子(以列计)

bool flag = false ;   //当前棋子位置是否合法

queen[0] = -1 ;      //第0列棋子准备,因一开始移动的就是第0列棋子

int count = 0 ;      //一共有多少种解法的计数器 ;

while(col>=0 ) //跳出条件是回溯到无法回溯时

{

queen[col]++ ;      //col列上的皇后走到下一行试试

if(queen[col] >= QUEEN) //当前列全部走完

{

queen[col] = -1 ; //当前列棋子置于准备状态

col-- ;        //回溯到上一列的棋子

if(col>=0)      //回溯时要清理如下行,斜线的标志位

{

col_YN[queen[col]] = false ;

passive_YN[queen[col] + col] = false ;

negative_YN[QUEEN-1 + col - queen[col]] = false ;

}

}

else

{

//先判断棋子所在行没有棋子

if(col_YN[queen[col]] == false)

{

flag = true ;

//以下检查当前棋子是否与之前的棋子斜线相交

if( passive_YN[queen[col] + col] == true || negative_YN[QUEEN-1 + col -      queen[col]] == true)

flag = false ;

else

flag = true ;

if(flag) // flag为真表示位置合法

{

if(col == QUEEN-1) //列到达最后,即最后一个皇后也找到位置,输出解

{

count++ ; //解法的数目加一 ;

cout<

for(int i=0;i

cout<

}

col_YN[queen[col]] = true ;// 当前行设为有棋子

passive_YN[queen[col] + col] = true ;//当前行正斜率方向有棋子

negative_YN[QUEEN-1 + col - queen[col]] = true ; //当前行负斜率方向                   上也有棋子

col++ ;

if(col >= QUEEN)

{ // 找到解后再次回溯找另外的解,这同上面无解回溯是一样的

col-- ;

col_YN[queen[col]] = false ;

passive_YN[queen[col] + col] = false ;

negative_YN[QUEEN-1 + col - queen[col]] = false ;//原理同回溯

}

flag = false ;

}

}

}

}

cout<

return 0 ;

}

八皇后问题的实现(C语言)

2008-01-05 20:41

八皇后问题主要靠回溯的方法实现, 与迷宫的实现相似, 但又困难了一些. 如迷宫的路径不因为上一步而改变, 八皇后的每一步都受约束于以前的步数, 并且, 迷宫只要找出一条路径就行,但八皇后则有很多的解法. 等等.

#include

#define N 8           // 定义棋盘的格数, 通过改变,也可以是4皇后, 16皇后, 9皇后什么的.

int chess[N][N] = {0}; // 棋盘

int count = 0; // 有多少种放法

int canput(int row, int col) // 确定某一格能不能放

{

int i,j;

for(i = 0; i < N; i ++)

{

if(chess[i][col] == 1) //有 同列的

{

return 0;

}

for(j = 0; j < N; j++)

{

if(chess[row][j]==1) //有同行的

{

return 0;

}

if(((i-row)==(j-col)||(i-row)==(col-j))&&chess[i][j]==1) // 对角线上有的

{

return 0;

}

}

}

return 1;

}

void print_chess() // 打印放置的方案

{

int i, j;

for(i = 0; i < N; i++)

{

for(j = 0; j < N; j++)

{

printf("%d ", chess[i][j]);

}

printf("\n");

}

printf("\n");

}

int put(int row)     // 放置棋子, row是从哪一行开始, 通常是0

{

int j, s;

for(j = 0; j < N; j++) // 此一行的每一个格子都要试试能不能放

{

if(canput(row, j)) // 假如这格能放的话

{

chess[row][j] = 1; // 放置

if(row == N-1) // 已经到了最后一行, 那么肯定成功******************************************************

{

count = count +1;

print_chess();

chess[row][j] = 0; //成功后, 寻找下一种方法

continue;

}

s = put(row+1); // 放置下一行的

if(s == 0)    // 假如下一行不能放

{

chess[row][j] = 0; // 那么这格是放错了的, 清除

continue;           // 找本行的下一个方格

}

else

{

break;

}

}

}

if(j==N)    // 如果这一行的每个空格都不能放置

{

return 0; // 那么本行放置失败

}

else

{

return 1; // 本行放置成功

}

}

int main()

{

int s ;

s = put(0); // 放置

printf("the number of put way is %d\n", count); //打印信息

return 0;

}

这个程序有个奇怪的地方, 就是在有星号的那一行, 当把chess[row][j] = 0, continue;两句去掉时,发现程序依然能正常运行. 原因就是: 当行比列多时, 假如皇后是的数目是列那么多, 是肯定放不成功的, 所以, 当程序要在最后一行的下一行放皇后时,怎么放也不成功,所以, 程序会不断调整以前的方法,但打印信息却在这里执行, 所以能打出正确信息. 但不建议去掉, 因为操作未知内存终究不是件好事.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值