- 区别于穷举法,回溯是有顺序有逻辑的,不罗列出,而是通过“某一步不合理性“,可以推翻这一步”相连的方案“;
- 在编码中,当一种子方案不合适是,进行所谓”回溯“一定要记得消除子方案的影响,此n_Queue即为对棋盘的标识;
代码说明:
- QueueNUM为行列数;
- 结束标志是SetQueue的测试行数刚超过范围,说明之前[0,QueueNUM-1]行都成功插入了,此时打印
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define QueueNUM 4
void InitializeP(int [][QueueNUM],int start);//start为开始置为0的开始行数
void printQueue(int [][QueueNUM]);
int safePlace(int,int,int [][QueueNUM]);
void SetQueue(int,int [][QueueNUM]);
int main()
{
int Board[QueueNUM][QueueNUM];
InitializeP(Board,0);
printQueue(Board);
SetQueue(0,Board);
return 0;
}
void SetQueue(int row,int A[][QueueNUM])
{
int i;
if(row==QueueNUM)//base case:输入序位
printQueue(A);
else
{
for(i=0;i<QueueNUM;i++)
if(safePlace(row,i,A))
{
A[row][i]=1;
SetQueue(row+1,A);//开始递归,在下一行插入
//递归结束时,影响的位置要重新归零
InitializeP(A,row);
}
}
}
void InitializeP(int A[][QueueNUM],int start)
{
int i,j;
for(i=start;i<QueueNUM;i++)
for(j=0;j<QueueNUM;j++)
A[i][j]=0;
}
void printQueue(int A[][QueueNUM])
{
int i,j;
for(i=0;i<QueueNUM;i++)
{
for(j=0;j<QueueNUM;j++)
printf("%2d",A[i][j]);
printf("\n");
}
printf("\n");
}
int safePlace(int row,int col,int A[][QueueNUM])
{
int i,j;
for(i=0;i<QueueNUM;i++)
if(A[row][i]!=0||A[i][col]!=0)
return 0;
for(i=1,j=1;i<=row&&j<=col;i++,j++)
if(A[row-i][col-i]!=0)
return 0;
for(i=1,j=1;i<QueueNUM-row&&j<QueueNUM-col;i++,j++)
if(A[row+i][col+i]!=0)
return 0;
for(i=1,j=1;row-i>=0&&col+j<QueueNUM;i++,j++)
if(A[row-i][col+j]!=0)
return 0;
for(i=1,j=1;j<=col&&i+row<QueueNUM;i++,j++)
if(A[row+i][col-j]!=0)
return 0;
return 1;
}