每周一算法:迭代加深A*

题目链接

AcWing 180. 排书

题目描述

给定 n n n 本书,编号为 1 ∼ n 1\sim n 1n

在初始状态下,书是任意排列的。

在每一次操作中,可以抽取其中连续的一段,再把这段插入到其他某个位置。

我们的目标状态是把书按照 1 ∼ n 1\sim n 1n 的顺序依次排列。

求最少需要多少次操作。

输入格式

第一行包含整数 T T T,表示共有 T T T组测试数据。
每组数据包含两行,第一行为整数 n n n,表示书的数量。
第二行为 n n n个整数,表示 1 ∼ n 1\sim n 1n 的一种任意排列。

同行数之间用空格隔开。

输出格式

每组数据输出一个最少操作次数。

如果最少操作次数大于或等于 5 5 5次,则输出5 or more

每个结果占一行。

数据范围

1 ≤ n ≤ 15 1≤n≤15 1n15

输入样例

3
6
1 3 4 6 2 5
5
5 4 3 2 1
10
6 8 5 3 4 7 2 9 1 10

输出样例

2
3
5 or more

算法思想

根据题目描述,需要对 1 ∼ n 1\sim n 1n的一个排列,进行若干次操作,在每一次操作中,可以抽取序列中连续的一段,再把这段插入到其他某个位置。问最少经过几次操作,可以将序列变为按照 1 ∼ n 1\sim n 1n 的顺序依次排列。

先考虑每一次操作的决策数量:

  • 当从序列中抽取长度为 i i i的一段时,有 n − i + 1 n-i+1 ni+1种选择。例如:对于长度 n = 6 n=6 n=6的序列中,抽取长度为 i = 3 i=3 i=3的连续一段,有 4 4 4种选择,如下图所示
    在这里插入图片描述
  • 对于每种抽法,有 n − i n-i ni种放法,即将长度为 i i i的一段插入其它 n − i n-i ni个空中。例如:
    在这里插入图片描述

那么每一步状态数量为 ( n − i ) × ( n − i + 1 ) (n-i)\times(n-i+1) (ni)×(ni+1),但将某一段向前移动,等价于将跳过的那段向后移动,因此每种移动方式被计算了两次,还要除以 2 2 2。所以状态空间的大小为 ∑ i = 1 n ( n − i ) × ( n − i + 1 ) / 2 ≤ ( 15 × 14 + 14 × 13 + . . . + 2 × 1 ) / 2 = 560 \sum_{i=1}^n(n-i)\times(n-i+1)/2\le(15\times14+14\times13+...+2\times1)/2=560 i=1n(ni)×(ni+1)/2(15×14+14×13+...+2×1)/2=560

考虑在 4 4 4步内找到答案,最多有 56 0 4 560^4 5604个状态,暴力搜索会超时。可以使用双向广搜 或者迭代加深A*(IDA* )来优化。

迭代加深A*

在A*算法算法中,将估价函数与优先队列BFS结合,提高了搜索效率。那么把估价函数与迭代加深的DFS结合就是迭代加深 A* \text{A*} A* IDA* \text{IDA*} IDA*)。

迭代加深 A* \text{A*} A*要限定一个深度,在不超过该深度的前提下执行DFS,若找不到解,就扩大深度限制,重新进行搜索;除此之外,还要设计一个估价函数,估算从每个状态到目标状态需要的“步数”。与 A* \text{A*} A*算法一样,估价函数需要遵守“预计值不大于未来实际步数”的准则。

基本思想是以迭代加深DFS的搜索框架为基础,把原来简单的深度限制加强为:若当前深度+未来估计步数>深度限制,则立即从当前分支回溯

估价函数

IDA* \text{IDA*} IDA*的算法的关键在于设计估价函数,那么本题的估价函数如何设计?考虑对于目标状态,第 i i i本书后边应该是第 i + 1 i+1 i+1本书,那么认为 i + 1 i+1 i+1 i i i的正确后继。

对于任意状态,考虑整个排列中错误的后继总数,将其记为tot,可以发现每次操作至多更改 3 3 3本数的后继,例如,将 346 346 346移动到 2 2 2的后面, 1 、 2 、 6 1、2、6 126的后继被更改,如下图所示:将346移动到2的后面,126的后继被更改
也就是说,在最理想的情况下,每次操作都能把 3 3 3个错误后继全部该对,那么消除所有错误后继的操作次数也至少需要 ⌈ t o t 3 ⌉ \lceil\frac{tot}{3}\rceil 3tot次。

因此,可以把一个状态state的估价函数设计为 h ( s t a t e ) = ⌈ t o t 3 ⌉ h(state)=\lceil\frac{tot}{3}\rceil h(state)=3tot,其中tot表示在当前状态state下书的错误后继总数。

算法实现

基本思想是使用迭代加深的方法,从 1 ∼ 4 1\sim4 14依次限制搜索深度,然后从起始状态出发进行DFS。对于当前状态:

  • 如果若当前步数+未来估计步数>深度限制,则搜索结束返回无解。
  • 如果到达最终状态,搜索结束返回有解。
  • 枚举要抽连续的一段的左右位置 [ L , R ] [L, R] [L,R],以及插入位置 i i i,将 [ L , R ] [L, R] [L,R]这一段插入到 i i i位置后
    • 继续搜索下一阶段的状态

代码实现

#include <bits/stdc++.h>
using namespace std;
const int N = 20;
int n, q[N], b[5][N]; //备份数组
int h() //估价函数
{int tot = 0; //统计错误后继总数for(int i = 0; i + 1 < n; i ++)if(q[i] + 1 != q[i + 1]) tot ++;return (tot + 2) / 3; //总数÷3向上取整
}
bool check()
{for(int i = 0; i < n; i ++)if(q[i] != i + 1) return false;return true;
}
//当前步数k,限制深度depth
bool dfs(int k, int depth)
{if(k + h() > depth) return false; //当前步数+估计步数超过限制if(check()) return true;//枚举抽取的左右两端和插入位置for(int L = 0; L < n; L ++)for(int R = L; R < n; R ++)for(int i = R + 1; i < n; i ++) //注意只需要枚举后面的插入位置即可{memcpy(b[k], q, sizeof q); //备份,方便恢复现场int x, y;//将[R+1,i]位置上的数向前移动for(x = R + 1, y = L; x <= i; x ++, y ++) q[y] = b[k][x];//将[L,R]位置上的数,向后移动for(x = L; x <= R; x ++, y ++) q[y] = b[k][x];if(dfs(k + 1, depth)) return true;memcpy(q, b[k], sizeof q); //备份,方便恢复现场}return false;
}
int main()
{int T;cin >> T;while(T --){cin >> n;for(int i = 0; i < n; i ++) cin >> q[i];int depth = 0;while(depth < 5 && !dfs(0, depth)) depth ++;if(depth >= 5) puts("5 or more");else cout << depth << '\n';}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/766042.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

智能风扇的新篇章:唯创知音WTK6900G语音识别芯片引领行业革新

随着科技浪潮的推进&#xff0c;智能化技术逐渐渗透到生活的每一个角落&#xff0c;家电领域尤为明显。风扇&#xff0c;这一夏日清凉神器&#xff0c;也通过智能化改造&#xff0c;焕发出前所未有的光彩。其中&#xff0c;智能语音控制功能的加入&#xff0c;为风扇的使用带来…

服务器软件express搭建web服务器

文章目录 1.express 是什么2.路由2.1&#xff08;参数一&#xff09;读取用户的请求&#xff08;request&#xff09;2.2&#xff08;参数二&#xff09;给用户响应&#xff08;response&#xff09;2.3&#xff08;参数三&#xff09;next()函数&#xff08;传递请求到下一个处…

[AIGC] 主流工作流引擎对比与适用场景介绍

主流工作流引擎对比与适用场景介绍 工作流引擎在业务流程管理中扮演着重要的角色&#xff0c;它可以帮助组织将复杂的工作流程自动化&#xff0c;降低错误率&#xff0c;提高工作效率。目前市面上有许多优秀的工作流引擎&#xff0c;各自都有着独特的优点和适用的场景。本文将介…

涨知识啦!如何使用3dMax和Vray渲染三维室内平面图效果图?

使用3dMax渲染三维室内平面图教程 在建筑和室内设计领域,3D平面效果图在建筑师或设计师与其客户之间更好地沟通方面发挥着重要作用。并不是每个人都能“阅读”建筑二维平面图及其所有技术元素,因此将该平面图转换为更易于理解的布局是很重要的。一个简单的方法是只使用2D图形…

SSL加密:保护数据传输的安全盾牌

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

AcWing 1250. 格子游戏 (并查集,坐标变换)

记录此题的目的&#xff1a; 明确二维的坐标可以映射到一维&#xff1a;在x和y都是从0开始的前提下&#xff0c;假如图形列数为n&#xff0c;(x,y)映射到一维可以写成x * n y。并查集并不好存储二维数据&#xff0c;如果遇到二维数据可以将其映射到一维。 Alice和Bob玩了一个…

Prometheus+Grafana 监控Tongweb7(by lqw)

文章目录 1.准备工作2.Tongweb7部署3.Prometheus部署4.上传jar包并配置Tongweb75.Prometheus配置6.安装和配置Grafana 1.准备工作 本次参考&#xff1a;Prometheus监控Tongweb容器 1.使用虚拟机ip&#xff1a;192.168.10.51&#xff08;tongweb&#xff09;&#xff0c;192.1…

Linux源码包安装

目录 一、transmission源码包安装 二、 nginx源码包安装 一、transmission源码包安装 1、下载编译环境所需的软件包依赖 2、下载transmision源码包到用户主目录下 https://github.com/transmission/transmission/releases/download/4.0.5/transmission-4.0.5.tar.xz 3、解压…

【python】学习笔记04-函数

4.1 函数介绍 1. 函数是&#xff1a; 组织好的、可重复使用的、用来实现特定功能的代码段 2. 使用函数的好处是&#xff1a; • 将功能封装在函数内&#xff0c;可供随时随地重复利用 • 提高代码的复用性&#xff0c;减少重复代码&#xff0c;提高开发效率 4.2 函数的定义 …

【PHP】通过PHP安装数据库并使数据初始化

一、前言 有些CMS在部署的时候不用使用数据库工具&#xff0c;而是通过数据库安装页面就能完成数据库创建和数据填充&#xff0c;所以自己就想动手做一个这样的功能&#xff0c;这样在给别人安装系统的时候就不用再那么麻烦了&#xff0c;直接一键安装解决了。 二、效果图 输…

基于骨骼的动作识别的行动结构图卷积网络

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 摘要Abstract文献阅读&#xff1a;基于骨骼的动作识别的行动结构图卷积网络1、研究背景2、方法提出3、关键结构3.1、A-links inference module (AIM)3.2、Structura…

【测试开发学习历程】MySQL分组查询与子查询 + MySQL表的联结操作

目录 1 MySQL分组查询与子查询 1.1 数据分组查询 1.2 过滤分组 1.3 分组结果排序 1.4 select语句中子句的执行顺序 1.5 子查询 2 MySQL表的联结操作 2.1 关系表 2.2 表联结 2.3 笛卡尔积 2.4 内部联结 2.5 外联结 2.6 自联结 2.7 组合查询 1 MySQL分组查询与子查询…

day16-环形链表

问题描述&#xff1a; 给定一个链表的头节点 head &#xff0c;返回链表开始入环的第一个节点。 如果链表无环&#xff0c;则返回 null。如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0…

更改默认的网络状态页面

目录 网络状态码 概念 分类 详解 页面更改 场景 步骤 网络状态码 概念 当浏览者访问一个网页时&#xff0c;浏览者的浏览器会向网页所在服务器发出请求。当浏览器接收并显示网页前&#xff0c;此网页所在的服务器会返回一个包含HTTP状态码的信息头用以响应浏览器的请求…

仿牛客社区项目所有PPT图片

文章目录 第1章 初识Spring Boot&#xff0c;开发社区首页1.1 课程介绍1.1.1 课程目标1.1.2 技术架构1.1.3 开发环境 1.2 搭建开发环境1.2.1 Apache Maven1.2.2 Intellij IDEA1.2.3 Spring Initializer1.2.4 SpringBoot 入门示例 1.3 Spring入门1.3.1 SpringBoot 全家桶1.3.2 S…

SpringBoot 邮件服务集成配置全面解析

前言 本文以网易邮箱&#xff08;及 163 邮箱&#xff09;为例&#xff0c;展示如何为 SpringBoot 项目集成邮件服务&#xff0c;其他邮箱配置类似&#xff0c;可以自行查看 Spring Email 指南 或是其他官方文档 授权码 首先我们需要获取授权码&#xff0c;用于后续配置&…

Xpath解析

目录 Xpath的简介&#xff1a; 简介&#xff1a; 相关概念&#xff1a; Xpath的使用&#xff1a; 安装&#xff1a; 用法&#xff1a; 第一步&#xff1a;准备html 第二步&#xff1a;将html构造出etree对象 第三步&#xff1a;使用etree对象的xpath()方法配合xpath表达…

JAVA——volatile,wait,notife

文章目录 volatile关键字简识jvm内存模型内存上的优化问题的产生volatile的作用 wait&#xff08;&#xff09;wait()的作用 notify&#xff08;&#xff09;notify的唤醒顺序 volatile关键字 volatile关键字可以保证内存的可见性&#xff0c;什么是内存的可见性呢&#xff1f…

二叉树的链式结构和遍历(下)

又见面了&#xff0c;小伙伴们。今天我们继续来学习二叉树&#xff0c;今天的内容相对来说比较容易理解&#xff0c;前提是需要你们自己动手画图才会好理解。眼过千遍不如手过一遍。所以小伙伴们要多动手哦。直接开始今天的学习吧 1.二叉树链式结构的实现 1.1 前置说明 在学习…

如何成为顶尖程序员?

如何成为顶尖程序员&#xff1f; 程序员是一种特殊的职业&#xff0c;但为什么大多数程序员无法达到顶尖水平&#xff1f;本文探讨了几个可能的原因&#xff0c;包括缺乏热情和动力、基础和原理的不足、实践和经验的匮乏&#xff0c;以及思考和创新的欠缺。了解这些原因可以帮助…