在回溯法的运用中的经典案例,问题如下:
在棋盘上放置8个皇后,使得他们互相不能攻击到,此时每个皇后的攻击范围为同行同列和同对角线(主副对角线),要求找出所有解。
这是问题的一个解
我们使用递归枚举(也就是回溯法)来求解这个问题。
先分析下问题的规模:从0行开始到第7行每行都必须有一个皇后,所以固定了行之后,按列来算就是全排列问题,排列数是8!=40320个,枚举数是不会超过它的,所以问题规模不大,可以进行回溯求解。
下面给出直观的代码
递归遍历每行,每层递归通过循环遍历每列,判断是否和之前的皇后位置冲突,未冲突则记录下来,冲突则返回上一层递归点。
#include <string.h>
#include <iostream>
using namespace std;
int t = 0;
int Arr[10] = { 0 };//用来存每行的皇后放在哪列上
//第一个参数是递归的行数,第二个参数的代表皇后的个数
void problem_queen(int cur, int n)
{
if (cur == n)//边界条件,递归完所有的行则退出
{
t++;
//打印出所有解
//for (int i = 0; i < n; i++)
//{
// i == n-1 ? printf("(%d,%d)", i, Arr[i]):printf("(%d,%d) ", i, Arr[i]);
//}
//printf("\n");
//return;
}
for (int i = 0; i<n; i++)//遍历n列
{
int ok = 1;
Arr[cur] = i;//将列数放入数组进行判断与前面皇后是否冲突
for (int j = 0; j<cur; j++)
{
if (Arr[cur] == Arr[j] || Arr[cur] + cur == Arr[j] + j || Arr[cur] - cur == Arr[j] - j) //判断纵行,主对角线和副对角线
{
ok = 0;
break;
}
}
if (ok)problem_queen(cur + 1, n);
}
}
int main()
{
memset(Arr, 0, sizeof(Arr));
problem_queen(0, 8);
return 0;
}
这里说明一下主对角线和副对角线是否冲突的判断,下图的横向是x(0 , 7)
纵向是y(0,7)
如图1
图1 格子中的值(x-y)标识了主对角线冲突,值相同即冲突
如图2,标记了副对角线的冲突
图2 格子中的值(x+y)
在上面的代码中,判断当前的皇后是否前面的皇后有冲突的循环可以去掉,由此可以优化代码的效率
#include <string.h>
#include <iostream>
using namespace std;
int vis[3][20];//判断纵向、主对角线、副对角线是否冲突,因为是逐行比较,所以横向肯定不会冲突
int t = 0;
int pos[10][10];
void search(int cur,int n)
{
if (cur == n)
{
t++;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
if (pos[i][j])
j == n-1 ? printf("(%d,%d)", i, j):printf("(%d,%d) ", i, j);
}
printf("\n");
return;
}
for (int i = 0; i < n; i++)
{
if (!vis[0][i] && !vis[1][i + cur] && !vis[2][cur - i + n])//在判断y-x时存的值有负值,所以这里对索引下标做个平移加个n
{
vis[0][i] = vis[1][i + cur] = vis[2][cur - i + n] = 1;
pos[cur][i] = 1;
search(cur + 1, n);
vis[0][i] = vis[1][i + cur] = vis[2][cur - i + n] = 0;//在退出这一层的递归之前要清除辅助变量记录的值,否则会影响下一次递归到该结点
pos[cur][i] = 0;
}
}
}
int main()
{
memset(vis, 0, sizeof(vis));
memset(pos, 0, sizeof(pos));
search(0, 8);
return 0;
}
以上就是八皇后问题的解法,注意的是,在使用回溯法时,使用到的辅助用的全局变量,在函数出口之前要将辅助变量及时恢复原状,以免影响下一次的递归,有多个出口时更要注意这个问题。
转载请注明出处:http://blog.csdn.net/gyh_420/article/details/75194011