今早上看了一篇英语阅读之后,莫名有些空虚寂寞冷。拿出算法书,研读回溯法。我觉得n皇后问题完全可以用暴力方式,即先对n个数进行全排列,得到所有结果的下标组合,问题规模为n!。

全排列花了比较久的时间才编写出来。主要是没有找对思路。最终我想到了递归,即对4个数进行全排列可以化为把【对3个数进行了全排列】的结果拿出来,在下标为1-4的位置上各插上一个数,一次类推。于是我编写了全排列类:

 //全排列
class Arrangment{
int[][]ans;
Arrangment(){}
Arrangment(int[] nums){
ans=createA(nums.length,nums);
}
void printNums(int[][] nums){
int row=nums.length;
int col=nums[].length;
int i,j;
for(i=;i<row;i++){
for(j=;j<col;j++)
System.out.print(nums[i][j]+" ");
System.out.print("\n");
}
}
int[][]createA(int rank,int []nums){
int[][] re;
if(rank>){
int[][] pre=createA(rank-,nums);
int row=pre.length;
int col=nums.length;
re=new int[row*rank][rank];
int index=;
int i,j,k,m;
for(i=;i<rank;i++){
for(j=;j<row;j++){
for(k=,m=;k<rank ;k++){
if(k==i){//如果列下标等于i(在0~rank)中循环
re[index][k]=nums[rank-];
int a;
a=;
}else{
re[index][k]=pre[j][m];
m++;
}
}
index++;
}
} }
else{
re=new int[][];
re[][]=nums[];
}
return re;
}
private int factorial(int n){
int re=;
while(n>=)
re*=(n--);
return re;
}
}

使用这个全排列类,就可以构造所有的问题的求解空间了。

暴力求解算法:

 class N_Queens{
int n;
N_Queens(int inN){
n=inN;
}
List<int[]> solved =new ArrayList<int[]>();
void solveByBrutal(){//穷举求解 boolean isComplied(int[] nums,int len){
int i,j;
for(i=0;i<len-1;i++)
for(j=i+1;j<len;j++){
int a=Math.abs(i-j);
int b=Math.abs(nums[i]-nums[j]);
if(a==b || b==0)
return false;
}
return true;
}
}

然后我开始研究怎么使用【回溯法】进行解题。我看了严奶奶书上的伪代码,以及树形结构实例,感触颇深。原来我以为这个问题和8数码问题一样需要进行树的按层遍历,已经使用队列结构的,但是他既然使用了一种递归的思想,并且是深度优先的。用递归的入栈出栈,在【剪掉枝丫】(问题不可解)和【找到一个解】之后,自动的求下一个解。

回溯法代码:

 class N_Queens{
int n;
N_Queens(int inN){
n=inN;
}
List<int[]> solved =new ArrayList<int[]>();
void solveByBackTrace(){
int[] nums=null;
trial(nums,0);
}
void trial(int [] nums,int i){//棋盘上的前i行已经放置了【符合条件】的棋子
if(i<n){
int j,k;
//第i行进行放置
for(j=0;j<n;j++){//在第j列上进行遍历
int[] node=new int[n];//新建结点
for(k=0;k<i;k++)
node[k]=nums[k];//拷贝父结点
node[i]=j;//第i行第j列上放上一个皇后
if(isComplied(node,i+1)){//符合条件
trial(node,i+1);//扩展它的子节点
}
}
}else{
solved.add(nums);
}
} boolean isComplied(int[] nums,int len){
int i,j;
for(i=0;i<len-1;i++)
for(j=i+1;j<len;j++){
int a=Math.abs(i-j);
int b=Math.abs(nums[i]-nums[j]);
if(a==b || b==0)
return false;
}
return true;
}
}

完整代码:

 import java.util.*;

 public class Main {

     public static void main(String[] args) {
while(true){
System.out.print("请输入皇后的数目:");
Scanner scan=new Scanner(System.in);
int n=scan.nextInt();
N_Queens problem=new N_Queens(n);
int []nums={1,2,3};
problem.isComplied(nums, 2);
problem.solveByBrutal();
problem.PrintChecker();
}
} } //全排列
class Arrangment{
int[][]ans;
Arrangment(){}
Arrangment(int[] nums){
ans=createA(nums.length,nums);
}
void printNums(int[][] nums){
int row=nums.length;
int col=nums[0].length;
int i,j;
for(i=0;i<row;i++){
for(j=0;j<col;j++)
System.out.print(nums[i][j]+" ");
System.out.print("\n");
}
}
int[][]createA(int rank,int []nums){
int[][] re;
if(rank>1){
int[][] pre=createA(rank-1,nums);
int row=pre.length;
int col=nums.length;
re=new int[row*rank][rank];
int index=0;
int i,j,k,m;
for(i=0;i<rank;i++){
for(j=0;j<row;j++){
for(k=0,m=0;k<rank ;k++){
if(k==i){//如果列下标等于i(在0~rank)中循环
re[index][k]=nums[rank-1];
int a;
a=0;
}else{
re[index][k]=pre[j][m];
m++;
}
}
index++;
}
} }
else{
re=new int[1][1];
re[0][0]=nums[0];
}
return re;
}
private int factorial(int n){
int re=1;
while(n>=1)
re*=(n--);
return re;
}
} class N_Queens{
int n;
N_Queens(int inN){
n=inN;
}
List<int[]> solved =new ArrayList<int[]>();
void solveByBrutal(){//穷举求解
int i;
int indexs[]=new int[n];
for(i=0;i<n;i++) indexs[i]=i;
Arrangment solve=new Arrangment(indexs);
int[][] solceSpace=solve.ans;//构造所有解空间
solved.clear();
for(i=0;i<solceSpace.length;i++){
if(isComplied(solceSpace[i],n))
solved.add(solceSpace[i]);
}
int a;
a=0;
}
void solveByBackTrace(){
int[] nums=null;
trial(nums,0);
}
void trial(int [] nums,int i){//棋盘上的前i行已经放置了【符合条件】的棋子
if(i<n){
int j,k;
//第i行进行放置
for(j=0;j<n;j++){//在第j列上进行遍历
int[] node=new int[n];//新建结点
for(k=0;k<i;k++)
node[k]=nums[k];//拷贝父结点
node[i]=j;//第i行第j列上放上一个皇后
if(isComplied(node,i+1)){//符合条件
trial(node,i+1);//扩展它的子节点
}
}
}else{
solved.add(nums);
}
} boolean isComplied(int[] nums,int len){
int i,j;
for(i=0;i<len-1;i++)
for(j=i+1;j<len;j++){
int a=Math.abs(i-j);
int b=Math.abs(nums[i]-nums[j]);
if(a==b || b==0)
return false;
}
return true;
} public String toString(){
int i,j;
String str=new String("");
for(i=0;i<solved.size();i++){
int [] out=solved.get(i);
for(j=0;j<out.length;j++){
str+=out[j];
str+=" ";
}
str+="\n";
}
return str;
}
void PrintChecker(){
int i,j,k;
String out=new String();
for(i=0;i<solved.size();i++){
int[] nums=solved.get(i);
for(j=0;j<nums.length;j++){
int l=nums[j];
int r=nums.length-1-nums[j];
for(k=0;k<l;k++) out+="□";
out+="■";
for(k=0;k<r;k++) out+="□";
out+="\n";
}
out+="\n";
}
System.out.print(out);
}
}

输出结果:

4皇后:

8皇后:

10皇后:

回溯法 | n皇后问题的更多相关文章

  1. 八皇后问题-回溯法(MATLAB)

    原创文章,转载请注明:八皇后问题-回溯法(MATLAB) By Lucio.Yang 1.问题描述 八皇后问题是十九世纪著名数学家高斯于1850年提出的.问题是:在8*8的棋盘上摆放8个皇后,使其不能 ...

  2. Java算法——回溯法

    回溯法一种选优搜索法,又称试探法.利用试探性的方法,在包含问题所有解的解空间树中,将可能的结果搜索一遍,从而获得满足条件的解.搜索过程采用深度遍历策略,并随时判定结点是否满足条件要求,满足要求就继续向 ...

  3. 回溯法解决N皇后问题(以四皇后为例)

    以4皇后为例,其他的N皇后问题以此类推.所谓4皇后问题就是求解如何在4×4的棋盘上无冲突的摆放4个皇后棋子.在国际象棋中,皇后的移动方式为横竖交叉的,因此在任意一个皇后所在位置的水平.竖直.以及45度 ...

  4. 实现n皇后问题(回溯法)

    /*======================================== 功能:实现n皇后问题,这里实现4皇后问题 算法:回溯法 ============================= ...

  5. HDU 2553 n皇后问题(回溯法)

     DFS Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u   Description ...

  6. 8皇后-----回溯法C++编程练习

    /* * 八皇后问题回溯法编程练习 * 在8×8的棋盘上,放置8个皇后,两个皇后之间不能两两攻击 * 也即,直线,垂直45度.135度方向不能出现两个皇后 * * copyright Michael ...

  7. 算法——八皇后问题(eight queen puzzle)之回溯法求解

    八皇后谜题是经典的一个问题,其解法一共有种! 其定义: 首先定义一个8*8的棋盘 我们有八个皇后在手里,目的是把八个都放在棋盘中 位于皇后的水平和垂直方向的棋格不能有其他皇后 位于皇后的斜对角线上的棋 ...

  8. js实现八皇后,回溯法

    八皇后问题:将八个皇后摆在一张8*8的国际象棋棋盘上,使每个皇后都无法吃掉别的皇后,一共有多少种摆法? 两个皇后不能同时在同一行,同一列,和斜对角线的位置上,使用回溯法解决. 从第一行选个位置开始放棋 ...

  9. 回溯法求解n皇后和迷宫问题

    回溯法是一种搜索算法,从某一起点出发按一定规则探索,当试探不符合条件时则返回上一步重新探索,直到搜索出所求的路径. 回溯法所求的解可以看做解向量(n皇后坐标组成的向量,迷宫路径点组成的向量等),所有解 ...

随机推荐

  1. axios的各种传参方式

    axios的各种传参方式 1. params方式 axios({ url: '/users', method: 'get', params: { id: '11111', name: '22222' ...

  2. vue+element 给表格添加数据,页面不实时刷新的问题

    由于页面加载时,使用了keep-alive,keep-alive具有数据缓存作用,当在添加页面添加成功时,返回主页面没有立即更新.数据有缓存. 解决办法如下: 将获取数据列表的方法放到activate ...

  3. [转帖]CHROME开发者工具的小技巧

    CHROME开发者工具的小技巧 https://coolshell.cn/articles/17634.html 需要仔细学习看一看呢. 2017年01月19日 陈皓 评论 58 条评论  64,08 ...

  4. 【HTML】前台input上传限制文件类型

    仅限制xls文件上传 <input id="uploadSkufile" type="file" value="批量导入" style ...

  5. 初始认知学习 .net core 逐步加深

    1.一般用空项目练手 2.一般你已经有数据库的情况下使用如下的方式 开始生成类的操作 这里我使用的是Database First模式,使用工具Scaffold-DbContext(数据库上下文脚手架) ...

  6. Exceptionless - 本地搭建

    搭建环境:Windows 10 参与文档:https://github.com/exceptionless/Exceptionless/wiki/Self-Hosting 运行环境: .NET 4.6 ...

  7. Laravel是怎样防止你的定时任务重复执行的

    基本介绍 有时候一个定时任务执行需要的时间可能会比我们想象的要长,这就会引起一个问题——当前任务还没有执行完毕的时候另一个相同的任务也会执行,从而导致任务重复.例如想象一下我们执行每分钟生成一次报告的 ...

  8. 浅谈Spring解决循环依赖的三种方式

    引言:循环依赖就是N个类中循环嵌套引用,如果在日常开发中我们用new 对象的方式发生这种循环依赖的话程序会在运行时一直循环调用,直至内存溢出报错.下面说一下Spring是如果解决循环依赖的. 第一种: ...

  9. Linux自有服务(2)-Linux从入门到精通第六天(非原创)

    文章大纲 一.设置主机名二.chkconfig三.ntp服务四.防火墙服务五.rpm管理(重点)六.cron/crontab计划任务(重点)七.学习资料下载八.参考文章   自有服务,即不需要用户独立 ...

  10. Elasticsearch+x-pack认证license过期处理

    介绍: x-pack是Elasticsearch中的一个plugin,主要功能是实现认证功能 报错: 类似下面这样的报错,是因为licese过期导致的 解决: 1.首先去Elasticsearch的官 ...