有兴趣的朋友可以讨论下,八皇后问题怎么样才能尽可能少的减少资源的使用,还有就是大家说说解答的思路,我觉得思路比直接贴代码好多了
解决方案 »
- java的Syntax error, insert ";" to complete ReturnStatement ,不知道什么原因。
- 怎样实现根据一个url地址打开网页,并保存源代码
- Java字符创赋值的问题
- JAVA用线程绘图
- 哪位有JAVA连接ORACLE时的所需的JAR包,或者告诉哪有下载 谢谢(本人找了好久,估计是没找对方向)
- 有了Lomboz all in one 还需要ECLIPSE吗?
- 网络文件传输 JAVA
- 提一个基础问题:web上,JAVA的全局变量是什么啊?类似于ASP的Application对象的东西。
- BufferedReader.read()如何使用?
- jbuilder初学,问题多多
- 遇到一个编译错误,麻烦大家帮我看下,谢谢
- 关于java导入的简单问题
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(0);// temp
list.add(1);// <--从1开始传入
// 其实八皇后的问题只需要解析前面4个值就可以了,我发现八皇后的解是对称的
// 比如说这个1,5,8,6,3,7,2,4 用9依次相减得到 9-1=8,9-5=4,1,3,6,2,7,5这个就是8开头的其中的一个解了
for (int i = 1; i < 9; i++) {
list.set(1, i);
test(list, 2);
}
} // result 用于存储已选结果 l为目标层数
public static void test(List<Integer> result, int l) {
if (l != 9) {
List<Integer> list = null;
list = check(result, l);
if (list != null && !list.isEmpty()) {
// 目标层数加1
l++;
// 遍历可选list
for (int i = 0; i < list.size(); i++) {
List<Integer> newResult = new ArrayList<Integer>();
newResult.addAll(result);
newResult.add(list.get(i));
test(newResult, l);
}
}
}
} // 检查函数
// 对已有结果进行解析,得出新的可选参数,返回的list就是新的可选项
// 比如说第一层选了1那么目标层就是2,第二层能选的结果就是3,4,5,6,7,8 然后通过循环吧结果作为新的result传进去
public static List<Integer> check(List<Integer> result, int l) {
int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
for (int i = 1; i < l; i++) {
int index = result.get(i);
if (a[index] != 0) {
a[index] = 0;
}
int t = 0;
if ((t = index - (l - i)) > 0) {
a[t] = 0;
}
if ((t = index + (l - i)) < 9) {
a[t] = 0;
}
}
ArrayList<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < a.length; i++) {
if (a[i] != 0) {
list.add(a[i]);
}
}
return list;
}
估计就是前面两楼提到的位运算。
没看文章,简单说下,反正是讨论。首先是个空表
1 2 3 4 5 6 7 8
2 O O O O O O O
3 O O O O O O O
4 O O O O O O O
5 O O O O O O O
6 O O O O O O O
7 O O O O O O O
8 O O O O O O O
放一个棋子用X表示,不能用的位置用-表示,第一次:
1 2 3 4 5 6 7 8
2 X - - - - - -
3 - - O O O O O
4 - O - O O O O
5 - O O - O O O
6 - O O O - O O
7 - O O O O - O
8 - O O O O O -
第二次,x表示之前放的,.表示之前标记不能用的
1 2 3 4 5 6 7 8
2 x . . . . . .
3 . . X - - - -
4 . - . - O O O
5 . O - . - O O
6 . O - O . - O
7 . O - O O . -
8 . O - O O O .
第三次:
1 2 3 4 5 6 7 8
2 x . . . . . .
3 . . x . . . .
4 . . . . X - -
5 . O . . . - O
6 . O . O . . -
7 . - . O - . .
8 . O . O - O .
第4次:
1 2 3 4 5 6 7 8
2 x . . . . . .
3 . . x . . . .
4 . . . . x . .
5 . X . . . . -
6 . - . O . . .
7 . . . - . . .
8 . - . O . O .
可以看到第7行一个O都没有了,所以这个位置【5,3】不能用。要换下一个。我画得有点问题,只是表示个想法。
类似这种“全0全1”用位运算很快,不用遍历。
我估计它的算法就是这个吧
public class Queens {
/*
* * 目前最快的N皇后递归解决方法* N Queens Problem* 试探-回溯算法,递归实现
*/ // sum用来记录皇后放置成功的不同布局数;upperlim用来标记所有列都已经放置好了皇后。
private static long sum = 0, upperlim = (1 << 8) - 1; // 试探算法从最右边的列开始。
public static void test(long row, long ld, long rd) {
if (row != upperlim) {
// row,ld,rd进行“或”运算,求得所有可以放置皇后的列,对应位为0,
// 然后再取反后“与”上全1的数,来求得当前所有可以放置皇后的位置,对应列改为1
// 也就是求取当前哪些列可以放置皇后
long pos = upperlim & ~(row | ld | rd);//所有可以放的位置
while (pos != 0) // 0 -- 皇后没有地方可放,回溯
{
// 拷贝pos最右边为1的bit,其余bit置0
// 也就是取得可以放皇后的最右边的列
long p = pos & -pos;//最右边的位置 // row + p,将当前列置1,表示记录这次皇后放置的列。
// (ld + p) << 1,标记当前皇后左边相邻的列不允许下一个皇后放置。
// (ld + p) >> 1,标记当前皇后右边相邻的列不允许下一个皇后放置。
// 此处的移位操作实际上是记录对角线上的限制,只是因为问题都化归
// 到一行网格上来解决,所以表示为列的限制就可以了。显然,随着移位
// 在每次选择列之前进行,原来N×N网格中某个已放置的皇后针对其对角线
// 上产生的限制都被记录下来了
test(row + p, (ld + p) << 1, (rd + p) >> 1);
// 将pos最右边为1的bit清零
// 也就是为获取下一次的最右可用列使用做准备,
// 程序将来会回溯到这个位置继续试探
pos -= p;
}
} else {
// row的所有位都为1,即找到了一个成功的布局,回溯
sum++;
}
}
public static void main(String[] args) {
test(0, 0, 0);
System.out.println(sum);
}