初次接触递归的思想,折腾了一天多,本想自己把算法写出来的,但是最后还是看的书上的代码,发现原来这么简单,真是自惭形秽,下面是书上的代码

#include <iostream>
using namespace std;

#define N 8

bool matrix[N + 1][N + 1] = {0};

bool IsLegal(bool matrix[N + 1][N + 1], const int &i, const int &j)
{
// 判断前面的i-1个棋子与matrix[i][j]是否冲突,i为1时合法

for (int m = 1; m <= i - 1; ++m) {
for (int n = 1; n <= N; ++n) { // 实际每一行只有一个棋子
if (matrix[m][n] == 1) {
if ( n == j || abs(i - m) == abs(j - n) ) // key, not bad
return false;
}
}
}
return true;
}

void Print(bool matrix[N + 1][N + 1])
{
static int count = 1;
printf("Case %d:\n", count++);
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
matrix[i][j] == 1 ? printf("%c ", 2) : printf(". ");
}
cout << endl;
}
cout << endl;
}

void Trial(const int i)
{ if (i > N) // 输出当前的合法布局
Print(matrix);
else
for (int j = 1; j <= N; ++j)
{
matrix[i][j] = 1;
if ( IsLegal(matrix, i, j) )
Trial(i + 1);
matrix[i][j] = 0; //如果一直成功的话,是执行不到这一行的
}
}

int main(void)
{
Trial(1);

return 0;
}主要的重点在于Trial函数,对于第i行,先将第j个放入皇后,然后看下会不会冲突,没有冲突的话,进入第i+1行,直至第8行,如果一直成功,matrix[i][j] = 0是不会执行的,但是一旦有冲突if ( IsLegal(matrix, i, j) ) 为假时,那么不会执行下一步了,而是将第i行第j列的皇后拿走,再继续试下一列看能不能放皇后

 如何向上递归:比如当第4行所有的位子都冲突,即第4行都为0,因为第4行是嵌套在第3行中的,当i等于3时,matrix[i][j] = 1; if ( IsLegal(matrix, i, j) ) 这两步执行的没有问题,但是执行Trial(4);时不会继续递归,而是执行matrix[3][j] = 0;

#include <iostream>
using namespace std;
#include<stdio.h>
int IsAttact(int **p,int i,int j)
{
for(int i1=0;i1<i;i1++)
{
for(int j1=0;j1<8;j1++)
{
if(p[i1][j1]==0)
{
if(j==j1||abs(i1-i)==abs(j1-j))
{return 0;}
}
}
}
return 1;
}
bool IsOK(int **p,int i)
{
int j = 0;
bool foundSafePos = false;
if(i==8)
{foundSafePos=true;}
else
{
while((!foundSafePos)&&(j<8))
{
if(IsAttact(p,i,j)==1)
{ //找到可以插入的位置
p[i][j]=0;
foundSafePos=IsOK(p,i+1);//到某一步执行不下去了,就会直接返回false而不会继续递归
if(!foundSafePos)
{
p[i][j]=1;//第i+1步不行的话,就直接令第i行的当前列往下走一个
j=j+1;
}
}
else
{
j=j+1;
}
}
}
return foundSafePos;
}
void main()
{
int **p=new int *[8];
for(int i1=0;i1<8;i1++)
{
p[i1] = new int[8];
}
for(int i2=0;i2<8;i2++)
{
for(int j2=0;j2<8;j2++)
{
p[i2][j2]=1;
}
}
bool IsSucceed=IsOK(p,0);
if(IsSucceed)
{
for(int i2=0;i2<8;i2++)
{
printf("%d %d %d %d %d %d %d %d \n",p[i2][0],p[i2][1],p[i2][2],p[i2][3],p[i2][4],p[i2][5],p[i2][6],p[i2][7]);
}
}
}

基本原理一样,因为是一开始自己写的,就想找出问题,并写完它。

 

posted on 2016-05-08 20:19  薄樱  阅读(520)  评论(0编辑  收藏  举报