N后问题(回溯)
在n*n格的棋盘上放置n个皇后,任何两个皇后不放在同一行同一列,同一斜线上,问有多少种放法。
回溯算法
是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。
但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。
可以把回溯法看成是递归调用的一种特殊形式。
回溯算法的求解过程,实质上是一个先序遍历一棵"状态树"的过程,只是这棵树不是遍历前预先建立的,而是隐含在遍历过程中。
代码
1.算法(确定有无位置)
bool place(int* paraSolution, int paraT)
{
int j;
for (j = 1; j < paraT; j ++)
{
if ((abs(paraT - j) == abs(paraSolution[j] - paraSolution[paraT])) || (paraSolution[j] == paraSolution[paraT]))//斜线冲突||列冲突
return 0;
}
return 1;
}
2.标记序号
void nQueen(int paraN)
{
int i;
int* solution = (int*)malloc((paraN + 1) * sizeof(int));
for (i = 0; i <= paraN; i ++)
solution[i] = 0;
backtracking(solution, paraN, 1);
}
3.回溯
void backtracking(int* paraSolution, int paraN, int paraT)
{
int i;
if (paraT > paraN)
{
for (i = 1; i <= paraN; i ++)
printf("%d ", paraSolution[i]);
printf("\r\n");
}
else
{
for (i = 1; i <= paraN; i ++)
{
paraSolution[paraT] = i;
if (place(paraSolution, paraT))
backtracking(paraSolution, paraN, paraT + 1);
}
}
}
4.总代码
#include <stdio.h>
#include <malloc.h>
#include <math.h>
bool place(int* paraSolution, int paraT)
{
int j;
for (j = 1; j < paraT; j ++)
{
if ((abs(paraT - j) == abs(paraSolution[j] - paraSolution[paraT])) || (paraSolution[j] == paraSolution[paraT]))//斜线冲突||列冲突
return 0;
}
return 1;
}
void backtracking(int* paraSolution, int paraN, int paraT)
{
int i;
if (paraT > paraN)
{
for (i = 1; i <= paraN; i ++)
printf("%d ", paraSolution[i]);
printf("\r\n");
}
else
{
for (i = 1; i <= paraN; i ++)
{
paraSolution[paraT] = i;
if (place(paraSolution, paraT))
backtracking(paraSolution, paraN, paraT + 1);
}
}
}
void nQueen(int paraN)
{
int i;
int* solution = (int*)malloc((paraN + 1) * sizeof(int));
for (i = 0; i <= paraN; i ++)
solution[i] = 0;
backtracking(solution, paraN, 1);
}
int main()
{
nQueen(6);
return 1;
}
2 4 6 1 3 5
3 6 2 5 1 4
4 1 5 2 6 3
5 3 1 6 4 2