问题描述:
给定一个n*n的棋盘,放置n个彼此无法攻击的皇后,在国际象棋中,皇后可以攻击与其在同一列或者同一行或者同一斜线上的旗子。也就是说,在n个皇后中,任意两个都不能放在同一列或者同一行或者同一斜线上。
解题思路:
x[t]表示第t行中皇后所在列,因此x数组[t1,t2…tn]是一个1-n的全排列。所以从第一行开始,一行一行的向下进行,在每一行中遍历每一列,然后监测是否满足,如果满足,则进入下一行,如果不满足,回溯到上一行。
在进行算法实现的时候,尽量使用迭代而不是递归。
递归思路:
#include <cstdio>
#include <algorithm>
#include <cmath>
#define N 100
using namespace std;
//递归代码
int x[N];
int sum;
int n;
int valid(int k) //监测k是否可以在该行中满足皇后条件
{
for(int i=1;i<k;i++)
{
if(abs(k-i) == abs(x[k] - x[i]) || x[i] == x[k]) // 同一列或者同一斜线
return 0;
}
return 1;
}
int queen(int t) //t对层数进行遍历
{
if(t>n && n>0)
sum++;
else
{
for(int i=1;i<=n;i++) //第一行的n个位置
{
x[t] = i;
if(valid(t))
queen(t+1);
}
}
return sum;
}
int main()
{
int t;
scanf("%d",&n);
t = queen(1);
if(n == 0)
t == 0;
printf("%d\n",t);
return 0;
}
迭代思路:
#include <cstdio>
#include <algorithm>
#include <cmath>
#define N 100
using namespace std;
//递归代码
int x[N];
int sum;
int n;
int valid(int k) //监测k是否可以在该行中满足皇后条件
{
for(int i=1;i<k;i++)
{
if(abs(k-i) == abs(x[k] - x[i]) || x[i] == x[k]) // 同一列或者同一斜线
return 0;
}
return 1;
}
int queen(int t) //t对层数进行遍历
{
x[1] = 0; //初始化
while(t>0)
{
x[t] += 1;
while(x[t] <= n && !valid(t)) //在范围之内但是不能放置
x[t] ++;
if(x[t] <= n) //如果没有找到 x[t] = n+1;
{
if(t == n)
sum++;
else
x[++t] = 0; //找到满足的进入下一层
}
else
t--; //回溯到上一层,再次进入while循环,x[t]+=1
}
return sum;
}
int main()
{
int t;
scanf("%d",&n);
t = queen(1);
printf("%d\n",t);
return 0;
}