n后问题-回溯法
时间:2022-04-22
本文章向大家介绍n后问题-回溯法,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
问题描述:
在n*n的棋盘上放置彼此不受攻击的n个皇后。按国际象棋的规则,皇后可以与之处在同一行或者同一列或同一斜线上的棋子。
n后问题等价于在n*n格的棋盘上放置n皇后,任何2个皇后不放在同一行或同一列的斜线上。
算法设计:
|i-k|=|j-l|成立,就说明2个皇后在同一条斜线上。可以设计一个place函数,测试是否满足这个条件。
1 当i>n时,算法搜索至叶节点,得到一个新的n皇后互不攻击放置方案,当前已找到的可行方案sum加1.
2 当i<=n时,当前扩展结点Z是解空间中的内部结点。该结点有x[i]=1,2,3....n共n个儿子节点。
对当前扩展结点Z的每个儿子节点,由place检察其可行性。并以深度优先的方式递归地对可行子树,或剪去不可行子树。
算法描述:
#include <iostream>
#include <cstdlib>
using namespace std;
class Queen{
friend int nQueen(int);
private:
bool Place(int k);
void Backtrack(int t);
int n,
* x;
long sum;
};
bool Queen::Place(int k)
{
for(int j=1;j<k;j++)
if((abs(k-j)==abs(x[j]-x[k]))||(x[j]==x[k]))
return false;
return true;
}
void Queen::Backtrack(int t)
{
if(t>n)
sum++;
else
for(int i=1;i<=n;i++)
{
x[t] = i;
if(Place(t))
Backtrack(t+1);
}
}
int nQueen(int n)
{
Queen X;
X.n = n;
X.sum = 0;
int *p = new int [n+1];
for(int i=0;i<=n;i++)
p[i] = 0;
X.x = p;
X.Backtrack(1);
delete [] p;
cout<<X.sum<<endl;
return X.sum;
}
int main()
{
nQueen(4);
nQueen(2);
nQueen(3);
return 0;
}
执行结果:
迭代回溯:
数组x记录了解空间树中从根到当前扩展结点的路径,这些信息已包含了回溯法在回溯时所需要的信息。利用数组x所含的信息,可将上述回溯法表示成非递归形式,进一步省去O(n)递归栈空间。
n后问题的非递归迭代回溯法Backtrack可描述如下:
#include <iostream>
#include <cstdlib>
using namespace std;
class Queen{
friend int nQueen(int);
private:
bool Place(int k);
void Backtrack(void);//.........
int n,
* x;
long sum;
};
bool Queen::Place(int k)
{
for(int j=1;j<k;j++)
if( ( abs(k-j) == abs(x[j]-x[k]) ) ||( x[j] == x[k] ) )
return false;
return true;
}
void Queen::Backtrack(void)//......
{
x[1] = 0;
int k = 1;
while(k>0)
{
x[k]+=1;
while( (x[k]<=n) && !(Place(k)) )//k还不是最后的叶子结点,且位置没有冲突
x[k] += 1;
if(x[k] <= n)
if(k == n)//k是叶子结点
sum++;
else
{
k++;
x[k] = 0;
}
else
k--;
}
}
int nQueen(int n)
{
Queen X;
X.n = n;
X.sum = 0;
int *p = new int [n+1];
for(int i=0;i<=n;i++)
p[i] = 0;
X.x = p;
X.Backtrack();//......
delete [] p;
cout<<X.sum<<endl;
return X.sum;
}
int main()
{
nQueen(4);
nQueen(2);
nQueen(3);
return 0;
}
执行结果:
- 数据库连接池-tomcat-jdbc食用笔记
- Java.NIO编程一览笔录
- Hbase 学习(三)Coprocessors
- Spring4+Spring MVC+MyBatis整合思路
- Zookeeper ACL权限配置及zkclient示例
- Spring Session 实现分布式会话管理
- 通过ambari安装hadoop集群(一)
- Hbase 学习(十) HBase Snapshots
- sqoop 常用命令整理(二)
- oozie 重新提交作业
- Hbase 学习(十一)使用hive往hbase当中导入数据
- WF追忆
- OpenCV和SVM分类器在自动驾驶中的车辆检测
- Hive Tunning(三) 最佳实践
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Vue路由懒加载
- 简单谈谈我的Android屏幕适配之路
- Js中Symbol对象
- 责任链模式
- Android Studio升级到3.0后遇到的坑
- Android原生项目集成React Native的方法
- Android编程之光线传感器用法详解
- Android Studio 3.0 新功能全面解析和旧项目适配问题
- Android开发中使用外部应用获取SD卡状态的方法
- Android编程使用光线传感器获取光线强弱的方法【LightSensorManager封装类】
- Android开发中的重力传感器用法实例详解
- 腾讯云TKE-Ingress案例: Nginx-Ingress 实现grpc转发
- 机器人软件中间层 yarp-Yet Another Robot Platforms
- 3分钟短文:Laravel写个命令行,你就是下一个Geek!
- Android开发多年每天Crud不清楚自己的技术?来刷刷大厂的高端技术面试题就知道了