Java解决N皇后问题

N皇后算法实现

共有三个类,其中一个类Stack可以由LinkedList代替

用做存放临时解的类

import java.util.LinkedList;

public class Stack<E> {
    private LinkedList<E> storage = null;

    public Stack() {
        storage = new LinkedList<E>();
    }

    public int size() {
        return storage.size();
    }

    public boolean empty() {
        return storage.isEmpty();
    }
    /**
     * LinkedList中于栈相关的源码可以看出Java官方的栈底是first,栈顶是last。
     * 将对象压入栈
     * */
    public void push(E e) {
        storage.addFirst(e);
    }
    /**
     * 返回并删除栈顶对象
     * */
    public E pop() {
        return storage.removeFirst();
    }
    /**
     * 引用栈顶对象但是不删除
     * */
    public E top() {
        return storage.getFirst();
    }

    /**
     * 根据索引查询栈元素
     * */
    public E get(int index) {
        return storage.get(index);
    }

    public String toString() {
        StringBuffer sb = new StringBuffer();
        int n = size();
        sb.append("有效解:");
        for(int i = 0 ; i < n ; i++) {
            sb.append(pop().toString());
        }
        return sb.toString();
    }   

}

皇后类

public class Queen {
    private int x,y;

    public Queen(int x,int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public boolean equals(Queen q) {
        return (this.x == q.getX()) //行冲突
                || (this.y == q.getY()) //列冲突
                || ((this.x + this.y) == (q.getX()) + q.getY()) //正对角线冲突
                || ((this.x - this.y) == (q.getX() - q.getY()));//反对角线冲突
    }

    @Override
    public String toString() {
        return "[x=" + this.x + ", y=" + this.y + "]"+",";
    }
}

算法实现类


public class QueenAlgorithm {
    /**
     * N皇后算法
     * 此版本只能找出一个解,但也因此拥有更快的效率
     * */
    public void placeQueens(int n) {
        Stack<Queen> solu = new Stack<Queen>(); //存放(部分)解的栈
        Queen q = new Queen(0,0);//从原点出发
        do {
            /**
             * 如果冲突,回溯上一个皇后
             * n <= solu.size() 表示当前已是全局解,回溯上一步尝试找到不同解
             * n <= q.getY() 表示当前行无解,需要回溯上一步
             * */
            if(n <= q.getY()) {
                q = solu.pop();
                q.setY(q.getY() + 1);
            } else {
                //通过已有皇后比较,尝试找到下一个皇后的位置 
                while((q.getY() < n) && (find(solu,q))) {
                    q.setY(q.getY() + 1);                       
                }               
                //若存在可摆位置,摆上皇后
                if(q.getY() < n) {
                    solu.push(q);
                    //找到全局解,将全局解打印出来
                    if(n <= solu.size()) {
                        System.out.println(solu.toString());                        
                    }
                    /**
                     * 转入下一行,从第0列开始
                     * q.setX(q.getX() + 1);                    
                     * q.setY(0);
                     * 不能通过这种方式改变q的值,会影响栈里的Queen对象的值
                     * 因为q跟栈里的元素指向同一个地址
                     * 必须通过新建Queen对象,将q指向与栈里对象的地址.              
                     */
                    q = new Queen(q.getX() + 1, 0);
                }
            }           
        }while(q.getX() < n);//用此条件结束循环无法找到所有解
    }

    private boolean find(Stack<Queen> solu,Queen q) {
        Queen temp;
        if(!solu.empty()) { //此处判断防止在第一次尝试时访问null引发异常
            for(int i = 0 ; i < solu.size() ; i++) {
                temp = solu.get(i);
                if(temp.equals(q)) {
                    return true;
                }
            }   
        }
        return false;
    }   
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值