boolean[] undiagonal = new boolean[16]// 反对角线安全标志
用上两个判断是否能放置棋子
若两个皇后位于同一行、同一列、同一对角线上,
则称为它们为互相攻击。
n皇后问题是指找到这 n 个皇后的互不攻击的布局。
n 行 n 列的棋盘上,主次对角线各有2n-1条。
利用行号i和列号j计算
主对角线编号k的方法是k = n+i-j-1;
计算次对角线编号k的方法是k = i+j
你主要是算法有些模糊罢了,现在我怕我说的不好将你弄的越来越混乱所以给你个叫形象的若是还不明白,call me
package 百度
//演示程序:n个皇后问题
import java.io.*
/*
在 n 行 n 列的国际象棋棋盘上,最多可布n个皇后。
若两个皇后位于同一行、同一列、同一对角线上,
则称为它们为互相攻击。
n皇后问题是指找到这 n 个皇后的互不攻击的布局。
n 行 n 列的棋盘上,主次对角线各有2n-1条。
利用行号i和列号j计算
主对角线编号k的方法是k = n+i-j-1;
计算次对角线编号k的方法是k = i+j
*/
//"n个皇后问题"之类定义
public class cQueen {
int n //皇后问题的大小
int col[]//数组,各列上有无皇后(0,1)
int md[] //数组,各主对角线有无皇后(0,1)
int sd[] //数组,各次对角线有无皇后(0,1)
int q[] //数组,第i行上皇后在第几列(0,n-1)
int Q //已布皇后数,计数
int r //n皇后问题的解的组数
//构造函数 n皇后问题的初始化
public cQueen(int m) {
n=mQ=0r=0
col=new int[n]
md=new int[2*n-1] //初始化0
sd=new int[2*n-1]
q=new int[n]
}
//函数:打印棋盘
public void showBoard() {
int i,j
for(i=0i<ni++) {
for(j=0j<nj++)
if(q[i]==j) System.out.print("1 ")
else System.out.print("0 ")
System.out.println()
}
r++//解的组数
System.out.println("---------------")
}
//求解n皇后问题
/*
此函数试图在n*n的棋盘的第i行上放一个皇后,
若找到可以放的位置,就递归调用自身试图在i+1行
放另一个皇后,若第i行是最后一行,则打印棋盘。
*/
public void resolve(int i) {
int j
// 在第i行给定后检查棋盘上的每一列
for(j=0j<nj++) {
//如果在第i行的第j列可以布放皇后
if(col[j]==0&&md[n+i-j-1]==0&&sd[i+j]==0){
Q++q[i]=j//布放皇后,第i行皇后在第几列
// 标记新布皇后的攻击范围
col[j]=md[n+i-j-1]=sd[i+j]=1
// 如果已经布了n个皇后(得到了一组解),
// 把棋盘(解)打印出来。
if(Q==n) showBoard()
// 否则,递归。在第i行第j列布放皇后的前提下,
//试探下一行(i+1行)在哪一列布皇后?
else if(i<n-1) resolve(i+1)
else resolve(0)//因为约定起始行可以任选
//移除在第i行的第j列新布的皇后,
//并消除所标记的攻击范围,为回溯作准备。
Q-- q[i]=0
col[j]=md[n+i-j-1]=sd[i+j]=0
//试探在第i行的第j+1列新布皇后的方案(新解)
}
} //下一列,j循环
//对于给定的行,列扫描完毕后,从这里回溯。
}
//输出解的个数
public void HowMany() {
System.out.println(n+"皇后问题共有解"+r+"组。")
}
//主方法main()
public static void main(String []args) {
//定义一个8皇后问题(有92组解)
cQueen Q1=new cQueen(8) //大于10,你的微机可能要死机!
//第一个皇后可以在任意一行布放
Q1.resolve(0) //参数在0到n-1之间任选
Q1.HowMany()
}
} //类Queen定义结束
关于看代码的人人都知道的小技巧,最小试探法来输出结果进行比较和分析
希望我解释的你能明白:把棋盘看成二维方阵,行从上到下编号0-7(就是i),列从左到右编号0-7(就是j),这样棋盘上每个点都可以表示为(i,j)
从键盘的右上角(0,7)到左下角(7,0)的对角线,以及这条线的平行线,就是反对角线,也就是这个程序里的undiagonal。显然这个反对角线上任意2点(i1,j1)和(i2,j2)都满足i1+j1=i2+j2.因为i+j可能的取值范围是从0到14,所以把这个数组的长度定义为16(事实上15就可以了)
从键盘的左上角(0,0)到右下角(7,7)的对角线以及平行线,就是对角线,就是diagonal。同理,这个对角线及其平行线上任意2点都满足i1-i2=j1-j2.i-j的范围是-7到7,为了避免出现负数,程序里在这里+7,也是一个长度为16的数组(还是15就够了)
程序一开始的时候,i=j=0,所有的安全标识都是true,所以(0,0)这个点会被输出。这时,把diagonal【7】置为false。因为(1,1),(2,2)等等这些点都和(0,0)在一条对角线上(因为0-0+7=1-1+7=2-2+7),所以把这些点的对应的diagonal都置为false,也就是把diagonal【7】置为false
并且把undiagonal【0】也置为false,但是因为undiagonal【0】对应的元素只有(0,0)(因为只有0+0=0),所以这个对这一步没什么影响。
然后一点点递推,回溯,步骤就是这样。希望你看得懂,如果不明白的话给我发消息吧
LZ您对编程的了解貌还不够深入。JAVA是解释型语言,C和C++是编译型语言,从效率上来说的话他们本来就不是同一个档次——解释型语言比编译型语言要慢。
但是从算法上来说,C++能实现的,JAVA乃至您所接触过的所有语言都能实现。不同的方面在于效率和代码的长度。
LZ要是不服气的话可以在网上搜索所有您想要的各种JAVA算法,都能找到。不过效率的话……刚才已经说了……
补充一点:LZ您说很难实现,这个本人同意,但是本人不同意您说的“不能”实现