首先该说我居然做出来吧,毕竟我超级菜(呜呜呜…)
思路是这样的:
和选择排列数的方式是一样的,用st[]数组记录过已经使用的列,接着采用dfs遍历每一行,这样的话就排除了每一行、每一列都是相同的,此外只剩下对角线的判断了
dfs(1)的遍历是在列的循环中
采用了res[]一维数组记录每一次选择的列,res[1]=2表示选择第一行的第二个元素
用ans[][]二维数组表示当前行采用的列,主要是后期判断对角线的元素的时候方便判断
dfs(1)的遍历是在列的循环中,每一次一个循环结束的时候需要恢复现场,主要是恢复所使用的
列的状态st[j]、所用的二维数组ans[k][j],这也是所用的列。res[i]是一维的不恢复也可以,因为下次会被直接覆盖掉,但是二维数组不会
对于对角线的判断是在一个checkans()函数中的,采用变量的形式分别判断对角线上的元素是否存在
但是设置dx dy数组都是一个单位长度的,皇后问题的放置也有可能是在(1,1) (5,5)的位置上
所以需要对对角线的长度进行处理
依次扩大倍数即可。
package dbfs;
import java.util.Arrays;
import java.util.Scanner;
public class n皇后问题 {
/**
* @param args
*/
static int N=10;
static int n;
static int ans[][]=new int [N][N];
static int res[]=new int [N];
static boolean st[]=new boolean[N];
static int dx[]={-1,-1,1,1};
static int dy[]={-1,1,-1,1};
public static boolean checkans() {
for(int i=1;i<=n;i++){
int a=i;
int b=res[i];
//得到行和列的下标
for(int x=0;x<4;x++){
for(int ii=1;ii<=n;ii++){
int aa=a+dx[x]*ii;
int bb=b+dy[x]*ii;
if(aa > n || aa<1 || bb>n || bb<1) continue;
else{
if(ans[aa][bb]==1) return false;
}
}
}
}
return true;
}
public static void dfs(int k) {
if(k >n){
if(checkans()){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(ans[i][j]==1)System.out.print("Q");
else {
System.out.print(".");
}
}
System.out.println();
}
System.out.println();
}
}
for(int j=1;j<=n;j++){
if(!st[j]){
st[j]=true;
res[k]=j;
ans[k][j]=1;
dfs(k+1);
st[j]=false;
ans[k][j]=0;
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scanner = new Scanner(System.in);
n=scanner.nextInt();
dfs(1);
}
}
方法2:剪枝
import java.util.Scanner;
public class Main {
/**
* 疑惑:
* 就是对于一个点(x,y)他的对角线上的点和反对角线上的点不是应该有很多个嘛,
* 可是dig[j-u+n]这样对于一个点只能得到一个啊
* 答案:这个结果得到的不是一个点,而是一个截距,对于在对一条斜线上的点他们的取值b是相同的
* 所以在选中一个点的时候,这个点正对角线和反对角线就确定了
* 以后再选择点的时候不可以选择和上一点相同的对角线了
* @param args
*/
static int N=20;
//数组开到20,因为u+j可能大于10!
static int n;
static char g[][]=new char [N][N];
static boolean st[]=new boolean [N];
static boolean col[]=new boolean [N];
static boolean row[]=new boolean [N];
static boolean dig[]=new boolean [N];
static boolean udig[]=new boolean [N];
public static void dfs(int u)
{
if(u>n){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
System.out.print(g[i][j]);
}
System.out.println();
}
System.out.println();
}
for(int j=1;j<=n;j++){
if(!st[j] && !dig[j-u+n] && !udig[u+j] ){
g[u][j]='Q';
st[j]=dig[j-u+n]=udig[u+j]=true;
dfs(u+1);
g[u][j]='.';
st[j]=dig[j-u+n]=udig[u+j]=false;
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scanner =new Scanner(System.in);
n=scanner.nextInt();
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
g[i][j]='.';
}
}
dfs(1);
}
}