每天刷个算法题20160519:回溯法解八皇后

版权所有。所有权利保留。

欢迎转载,转载时请注明出处:

http://blog.csdn.net/xiaofei_it/article/details/51502622

为了防止思维僵化,每天刷个算法题。已经刷了几天了,现在发点代码。

我已经建了一个开源项目,每天的题目都在里面:

https://github.com/Xiaofei-it/Algorithms

绝大部分算法都是我自己写的,没有参考网上通用代码。读者可能会觉得有的代码晦涩难懂,因为那是我自己的理解。

最近几天都是在写一些原来的东西,大多数是非递归。以后准备刷点DP、贪心之类的题。

下面是回溯法八皇后:

/**
 *
 * Copyright 2016 Xiaofei
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package xiaofei.algorithm;

/**
 * Created by Xiaofei on 16/5/19.
 */
public class EightQueensPuzzle {

    /**
     * 八皇后(回溯法)
     * pos[n]
     * 竖排:值相同
     * 左上到右下:i - j = pos[i] - pos[j]  -->  i - pos[i] = j - pos[j]
     * 左下到右上:i - j = pos[j] - pos[i]  -->  i + pos[i] = j + pos[j]
     *
     * 每次都要O(n^2)判断有点蛋疼,不知道有没有优化方案。
     * 现在自己优化一下:
     * hash判断
     * 竖排:hash[SIZE]
     * 左上到右下:i - pos[i] = j - pos[j] 从-(SIZE-1)到(SIZE-1) 为了从0开始,偏移(SIZE-1)
     * 左下到右上:i + pos[i] = j + pos[j] 从0到2*(SIZE-1)
     */

    private static final int SIZE = 8;

    private static int number = 0;

    private static void print(int[] pos) {
        System.out.println(++number);
        int length = pos.length;
        for (int i = 0; i < length; ++i) {
            System.out.print(" " + pos[i]);
        }
        System.out.println();
        for (int i = 0; i < length; ++i) {
            for (int j = 0; j < pos[i]; ++j) {
                System.out.print('+');
            }
            System.out.print('*');
            for (int j = pos[i] + 1; j < SIZE; ++j) {
                System.out.print('+');
            }
            System.out.println();
        }
    }

    public static void calculate() {
        int[] pos = new int[SIZE];
        boolean[] hash1 = new boolean[SIZE];
        boolean[] hash2 = new boolean[SIZE * 2 + 1];
        boolean[] hash3 = new boolean[SIZE * 2 + 1];
        int last = 0;
        pos[last] = -1;
        while (last >= 0) {
            if (last == SIZE) {
                print(pos);
                --last;
            } else {
                boolean flag = false;
                if (pos[last] >= 0) {
                    hash1[pos[last]] = false;
                    hash2[last - pos[last] + SIZE - 1] = false;
                    hash3[last + pos[last]] = false;
                }
                while (pos[last] < SIZE - 1) {
                    ++pos[last];
                    if (!hash1[pos[last]] && !hash2[last - pos[last] + SIZE - 1] && !hash3[last + pos[last]]) {
                        hash1[pos[last]] = true;
                        hash2[last - pos[last] + SIZE - 1] = true;
                        hash3[last + pos[last]] = true;
                        ++last;
                        if (last < SIZE) {
                            pos[last] = -1;
                        }
                        flag = true;
                        break;
                    }
                }
                if (!flag) {
                    --last;
                }
            }
        }
    }
}
时间: 2024-11-13 17:04:30

每天刷个算法题20160519:回溯法解八皇后的相关文章

暴力回溯法 解八皇后

国际象棋 八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例.该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法. public class _8Queen { //回溯法,暴力解8皇后 private static int ways = 0; //返回解法个数 public static int f8queen() { int[][] board = new int

ACM:回溯法,八皇后问题,素数环

(一)八皇后问题 (1)回溯法 #include <iostream> #include <string> #define MAXN 100 using namespace std; int tot = 0, n = 8; int C[MAXN]; void search(int cur) { if(cur == n) ++tot; //递归边界,只要走到了这里,所有皇后必然不冲突 else for(int i = 0; i < n; ++i) { int ok = 1; C

每天刷个算法题20160526:BFS解决八数码问题(九宫格问题)

版权所有.所有权利保留. 欢迎转载,转载时请注明出处: http://blog.csdn.net/xiaofei_it/article/details/51524864 为了防止思维僵化,每天刷个算法题.已经刷了几天了,现在发点代码. 我已经建了一个开源项目,每天的题目都在里面: https://github.com/Xiaofei-it/Algorithms 绝大部分算法都是我自己写的,没有参考网上通用代码.读者可能会觉得有的代码晦涩难懂,因为那是我自己的理解. 最近几天都是在写一些原来的东西

回溯法求解八皇后问题---(初步、未优化)

首先介绍一下回溯算法: 定义来自<百度百科>......名字着很高大上,实际上就是试探法,逐步试错找到最终的可行解. 重要的一点是解空间通常是在搜索可行解过程中动态产生的,所以程序中通常利用到递归的算法,如后面介绍的八皇后问题.这点区别与于前段时间所写的模拟退火算法,模拟退火是首先确定解空间,然后以一定的概率接受当前发现的次优解,从而有更大的可能避免局部最优而得到全局最优. 简单介绍一下八皇后问题: 在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或

【基础算法】回溯法与八皇后问题

在国际象棋中,皇后是最强大的一枚棋子,可以吃掉与其在同一行.列和斜线的敌方棋子.比中国象棋里的车强几百倍,比她那没用的老公更是强的飞起(国王只能前后左右斜线走一格).上图右边高大的棋子即为皇后. 八皇后问题是这样一个问题:将八个皇后摆在一张8*8的国际象棋棋盘上,使每个皇后都无法吃掉别的皇后,一共有多少种摆法?此问题在1848年由棋手马克斯·贝瑟尔提出,岂止是有年头,简直就是有年头,82年的拉菲分分钟被秒的渣都不剩. 八皇后问题是典型的回溯法解决的问题,我们以这个问题为例介绍回溯法. 所谓回溯法

用递归和回溯法实现八皇后问题

问题描述: 八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例.该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋棋盘上放置八个皇后,使得任意两个皇后不能互相攻击,即任何行.列或对角线(与水平轴夹角为45°或135°的斜线)上不得有两个或两个以上的皇后.对于这个问题数学家高斯认为有76种方案.1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果.计算机发明后,有多种计算机语言可以解决此问题. 问题分析 在这里我们可以声明一个

【回溯法】八皇后问题(递归和非递归)

先贴代码,分递归回溯法和非递归回溯法 递归回溯法,代码如下: // test.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <iostream> #include <stdio.h> using namespace std; int a[9] = {0}; int n = 8; int count = 0; bool check

回溯法解决八皇后问题

八皇后问题是学习回溯算法时不得不提的一个问题,用回溯算法解决该问题逻辑比较简单. 下面用java版的回溯算法来解决八皇后问题. 八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例.该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法. 思路是按行来规定皇后,第一行放第一个皇后,第二行放第二个,然后通过遍历所有列,来判断下一个皇后能否放在该列.直到所有皇后都放完,或者放哪

回溯法与八皇后问题

tail recursion 函数在调用的时候,会提前创建一个栈空间,给传递的参数也分配空间,当函数结束返回上层函数的时候,一些局部变量需要从栈中弹出并恢复到调用子函数之前的值,返回到上一个函数调用子函数之前的现场.如果是尾递归,从子函数返回的时候这个函数同时也会结束了,所以没有必要恢复一些局部变量,直接把局部变量的栈空间删除.因此一个尾递归的函数根本不需要使用栈来给子函数变量空间,可以直接使用当前变量的值为新参数的值. backtracking 八皇后问题 用一个类Queens表示棋盘上现在的