n皇后、棋盘某个位置不能放置皇后和2n皇后问题

一、n皇后

数据结构介绍

a[i] = j 代表第i行的皇后放置在第j列

n皇后算法中的place(int a[],int i)函数的作用是判断当前放置的皇后是否与之前放置的皇后有冲突,没有冲突则可以放置。

java 代码

public static boolean place(int a[],int i)
{
for(int j = 0;j<i;j++)
{
if(a[i] == a[j] || Math.abs(i-j)==Math.abs(a[i]-a[j]))
return false;
}
return true;
}

public static void nQ(int i)
{
if(i>=n)
{
num++;
return;
}
/*
* 第i行尝试所有的列,如果可以放置进入下一行
* 因为此处使用的是递归结束后回到原来的地方继续
* 运行,每次获得结果的递归运算都是互不干扰的,因此不需要使用
* 明显的回溯a数组
*/
for(int j = 0;j<n;j++)
{
//第i行放置在第j列
a[i] = j;
if(place(a,i))
{
nQ(i+1);
}
}
}

//主函数

public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("棋盘大:");
n = in.nextInt();
nQ(0);
System.out.println(num);
}

二、棋盘某个位置不能放置皇后

使用二维数组arr[][]存放是否可以放置皇后的规定,如果可以放置此位置数据为1反之为0

public static void nQ(int i)
{
if(i>=n)
{
num++;
return;
}

for(int j = 0;j<n;j++)
{
//第i行放置在第j列
a[i] = j;

if(arr[i][a[i]]==0)//相对比n皇后没有约束问题只有此处有变化
continue;
if(place(a,i))
{
nQ(i+1);
}
}
}

//主函数

public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("棋盘大:");
n = in.nextInt();
a = new int[n];
arr = new int[n][n];
//初始化棋盘
System.out.println("棋盘布局:");
for(int i = 0;i<n;i++)
{
for(int j = 0;j<n;j++)
{
arr[i][j] = in.nextInt();
}
}
nQ(0);
System.out.println(num);
}

三、2n皇后(黑皇后和白皇后,黑白皇后不能放置在一个地方,共存在一个棋盘上一共可以合作几次)加上规定某些位置不能放置皇后问题

思想:黑皇后在第i行时先选一个自己可以放置的节点占据,之后白皇后在黑皇后选完之后将剩下的全部选择一遍,白皇后每选择一个合适的位置,黑白皇后一起进入下一行的选择当白皇后选择了自己当前可以选择的所有位置之后,黑皇后在第i行再找一个合适的位置,由此循环递归,知道所有的位置都选择一遍位置。

注:此处需要注意的是arr[][]数组是共享的变量且黑白皇后共同操作,因此黑白皇后每次占据试探完位置之后,均需要回溯。(例如:内部的白皇后不进行回溯,当循环递归回来,再次轮到黑皇后在第i行选的时候,所有的位置都已经被白皇后试过了(且因为没有回溯)所以黑皇后就认为自己没有位置可以选了,程序就由此结束了,n皇后问题的时候,虽然也是共享的数组a[],当时每次进行递归深入的时候总是操作的数组的后部分,当递归结束的时候,还是给a[]附自己得值,不会受以前递归的影响)

代码:

public static void doubleNQ(int i)
{
if(i>=n)
{
num++;
return;
}
//浏览所有的列
for(int j = 0;j<n;j++)
{
a[i] = j;
if(arr[i][a[i]]==0)
continue;
//可以放进入下一行
if(place(a,i))
{
arr[i][a[i]] = 0;
int m = 0;
for(m = 0;m<n;m++)
{
b[i] = m;
if(arr[i][b[i]]==0)
continue;
if(place(b,i))
{
arr[i][b[i]] = 0;
nQ(i+1);
}
arr[i][b[i]] = 1;//回溯
}
}
arr[i][a[i]] = 1;//回溯
}
}

//主函数

public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("棋盘大:");
n = in.nextInt();
a = new int[n];
b = new int[n];
arr = new int[n][n];
//初始化棋盘
System.out.println("棋盘布局:");
for(int i = 0;i<n;i++)
{
for(int j = 0;j<n;j++)
{
arr[i][j] = in.nextInt();
}
}
doubleNQ(0);
System.out.println(num);
}



  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值