题目:
思路:
代码段中的Check();方法没有对同一行之前的位置进行判断,是因为同一行是从左到右依次放置的,若前面放了则直接是下一行的判断,不会是相邻右侧的位置进行放置,则不需要进行判断,同理右侧,下方都不用,因为还没有进行皇后的放置,本题是回溯法经典的应用,递归的思想
import java.util.Scanner;
public class Main {
static int n,cnt=0;
static int map[][];
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
n=in.nextInt();
map=new int[n][n];
for(int i=0;i<n;i++)//棋盘具体值的录入(0或1)
for(int j=0;j<n;j++)
map[i][j]=in.nextInt();
put(0,2);//从第一行开始进行白皇后的放置,2表示白皇后,3表示黑皇后
System.out.println(cnt);
}
//放置皇后
public static void put(int t,int s) {
//进行当前类型皇后放置是否到达棋盘最后一行
if(t==n) {
if(s==2) put(0,3);//若白皇后放置成功,则进行黑皇后放置
else cnt++;//放置方法找到一种,计量数+1
return;//当前整体放置过程结束,进行回溯
}
//对每一行的值逐个进行操作
for(int i=0;i<n;i++) {
if(map[t][i]!=1) continue;//判断当前位置是否为1
if(check(t,i,s)) {//判断是否满足题目要求,满足则赋值
map[t][i]=s;
}else
continue;//不满足,同一行,下个位置
put(t+1,s);//下一行皇后的位置
map[t][i]=1;//回溯的关键
}
return;//相应的回溯
}
//判断函数
public static boolean check(int t,int i,int s) {
for(int q=t-1;q>=0;q--) {//当前位置上方是否进行了相同皇后的放置,这行一下还没放
if(map[q][i]==s) return false;
}
for(int q=t-1,w=i-1;q>=0&&w>=0;q--,w--) {//检查左对角线,这行一下的还没放,不检查
if(map[q][w]==s) return false;
}
for(int q=t-1,w=i+1;q>=0&&w<=n-1;q--,w++) {//检查右对角线,这行一下还没放,不检查
if(map[q][w]==s) return false;
}
return true;
}
}
法二:
import java.util.Scanner;
public class Main
{
static int sum=0;//统计符合的数目
public static void main(String[] args)
{
Scanner db=new Scanner (System.in);
int n=db.nextInt();
int arr[]=new int [n]; //皇后放置位置
int wee[][]=new int [n][n];// 接受输入时的0 1
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
wee[i][j]=db.nextInt();
queen(0, 0, arr, wee);//递归调用
System.out.println(sum);
}
public static int queen(int su, int k, int arr[], int[][] wee)
//su==0表示落子的是白皇后 为1 表示落子的是黑皇后 k表示第k个皇后
{
if(k==arr.length)//如果所有皇后都放置
{
if(su==0)//判断放置的是否是白皇后
{
arr=new int[arr.length]; //如果白皇后都被放置,初始化黑皇后的位置
queen(su+1, 0, arr, wee);
}
if(su==1)//判断放置的是否是白皇后
sum++; //统计2n皇后的放置种数
return sum;
}
for(int i=0; i<arr.length; i++)//判断第k个皇后位置(列数)行数为k
{
if(wee[k][i]==0) //如果当前位置坐标值为零,则不能放置皇后
continue;
int j;
for(j=0; j<k; j++)//前k-1个皇后位置(列数)行数 为j
if(arr[j]==i||Math.abs(arr[j]-i)==(k-j))//判断皇后之间是否存在同一列,统一对角线冲突
break;
if(j==k)//条件成立时表示第k个与之前的没有冲突
{
arr[k]=i; //第k个皇后位置
wee[k][i]=0; //将此位置即为0 表示不能再这放置皇后
queen(su, k+1, arr, wee); //递归调用下一层
wee[k][i]=1;
}
}
return sum;
}
}