AStar 最坏情况\(O(log_2560 ^ 4)\)

用\(AStar\)算法做了这题,程序跑了\(408ms\)。

相比于\(IDA*\)的\(100ms\)左右要慢上不少。

且\(A*\)由于是\(bfs\),代码长度也较长。

跑的慢的原因应该有两点:

  • 用了三个\(STL\),垃圾STL毁我青春
  • 这题的指数暴涨,是\(560\),所以\(log\)反而比前几次叠加要大。

使用的估价函数是一样的,即:

\(h(n) = \lceil\frac{相邻位置不对的对数}{3}\rceil\)

估价函数详细的证明 & 解释见 y总的题解


总结了一下应该在何时选择 \(A*\) 或 \(IDA*\):

  • 需要最小字典序时,状态表示很大,指数增长较快时,使用\(IDA*\)
  • 若状态容易表示,指数增长较慢时,使用\(A*\)(注意需要最小字典序时不能用\(A*\),因为他不是按照顺序搜索的)。

C++ 代码

#include <cstdio>
#include <iostream>
#include <unordered_set>
#include <queue>
using namespace std;
typedef unsigned long long ULL;
const int N = 15, B = 17;
int n;
struct State{
//v表示当前的状态,step表示步数,f表示当前估计值(答案)
int v[N], step, f;
//重载小于号
bool operator < (const State &x) const{
return f > x.f;
}
}Start;
//检测是否到了目标状态
bool check(State x){
for(int i = 0; i < n; i++)
if(x.v[i] != i + 1) return false;
return true;
}
//用于检测一个状态是否已经访问过了
unordered_set<ULL> s;
priority_queue<State> q; //hash
ULL get(State x){
ULL res = 0;
for(int i = 0; i < n; i++)
res = res * B + x.v[i];
return res;
}
int f(State x){
int res = 0;
for(int i = 1; i < n; i++)
if(x.v[i] - 1 != x.v[i - 1]) res++;
return res % 3 ? res / 3 + 1 : res / 3;
}
int bfs(){
while(q.size()) q.pop();
Start.step = 0; Start.f = f(Start);
q.push(Start); s.insert(get(Start));
while(!q.empty()){
State u = q.top(); q.pop();
if(u.f >= 5) return 5;
if(check(u)) return u.step;
for(int l = 1; l < n; l++){
for(int i = 0; i + l - 1 < n; i++){
int j = i + l - 1;
for(int k = i + l; k < n; k++){
State v;
for(int f = 0; f < n; f++) v.v[f] = u.v[f];
for(int f = j + 1, t = i; f <= k; f++, t++)
v.v[t] = u.v[f];
for(int f = i, t = i + k - j; f <= j; f++, t++)
v.v[t] = u.v[f];
if(s.count(get(v)) > 0) continue;
s.insert(get(v));
v.step = u.step + 1;
v.f = v.step + f(v);
q.push(v);
}
}
}
}
return 5;
} int main(){
int T; scanf("%d", &T);
while(T--){
s.clear();
scanf("%d", &n);
for(int i = 0; i < n; i++)
scanf("%d", &Start.v[i]);
int res = bfs();
if(res >= 5) puts("5 or more");
else printf("%d\n", res);
}
return 0;
}

AcWing 180. 排书的更多相关文章

  1. AcWing 1023. 买书 完全背包

    //完全背包 求方案数目 //f[i][j] 只从前i个物品中选,且总体积恰好为j的方案的集合 //f[i][j]=f[i-1][j]+f[i-1][j-v*1]+f[i-1][j-v*2]+...f ...

  2. AcWing 【算法提高课】笔记02——搜索

    搜索进阶 22.4.14 (PS:还有 字串变换 A*两题 生日蛋糕 回转游戏 没做) 感觉暂时用不上 BFS 1. Flood Fill 在线性时间复杂度内,找到某个点所在的连通块 思路 统计连通块 ...

  3. python库-collections模块Counter类

    Counter类主要是用来跟踪值出现的次数.它是一个无序的容器类型,以字典的键值对形式存储,其中元素作为key,其计数作为value. demo: all_words = [] # 列表里面是汉字(可 ...

  4. [No00005F]读书与心智

    读千卷书,行万里路,不够…还得有个对谈者相伴,才更有意思.十月七号晚上,与友人谈读书,线上直播,三百观众相伴,四小时畅谈,不亦乐乎! Part1:读书的载体 散发出最浓郁的知识芬芳和铭刻下最隽永的历史 ...

  5. 本周实验的PSP0过程文档

    项目计划总结:       日期/任务      听课        编写程序         阅读相关书籍 日总计          周一      110           60         ...

  6. CodeForces 294B Shaass and Bookshelf 【规律 & 模拟】或【Dp】

    这道题目的意思就是排两排书,下面这排只能竖着放,上面这排可以平着放,使得宽度最小 根据题意可以得出一个结论,放上这排书的Width 肯定会遵照从小到大的顺序放上去的 Because the total ...

  7. 第三周pspo过程文档

    团队协作:     日期/任务      听课        编写程序         阅读相关书籍 日总计          周一      110          60             ...

  8. pspo过程文档

    项目计划总结:       日期/任务      听课        编写程序         阅读相关书籍 日总计          周一      110          60         ...

  9. 《Word排版艺术》读后感,兼谈LaTeX

    我有两年多的LaTeX使用经验,用它排实验报告.毕业论文和书籍(半本):Word的使用时间长一些,但真正用好也不过是近一两年的事.这两个软件我都 用得很熟,我想我可以一边谈谈读<Word排版艺术 ...

随机推荐

  1. innodb为什么需要doublewrite(转)

    InnoDB的page size默认是16KB,而操作系统的一个block size是4KB,磁盘io block则更小.那么InnoDB的page刷到磁盘上要写4个操作系统block,在极端情况下( ...

  2. Html+css 一个简单的网页模板

    一个简单的网页模板,有导航.子菜单.banner部分 1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN&q ...

  3. Python基础数据类型与for循环

    数据类型:int,bool,str,list, tuple元组,dict字典. 1.数字:12,3,4 在使用print打印数字时,在终端界面中无法判断出打印的是什么类型,当我们需要知道一个值是什么类 ...

  4. 记php多张图片 合并生成竖列 纵向长图(可用于商品详情图合并下载)

    <?php namespace app\mapi\common\image; /** * 拼接多幅图片成为一张图片 * * 参数说明:原图片为文件路径数组,目的图片如果留空,则不保存结果 * * ...

  5. FL Studio采样设置之时间拉伸栏

    今天小编将带领大家了解一下FL Studio采样设置页面中的时间拉伸栏知识,该栏目包含了和采样音频的时间拉伸相关的设置.其右边是一个时间伸缩方式下拉列表,里面列出了很多种类的伸缩方式,自动方式是默认的 ...

  6. mock模拟接口返回数据

    mock,是python中模拟接口返回数据 1.安装 pip install mock import unittest from mock import Mock def add(a,b): pass ...

  7. java基础:CompletionStage接口

    CompletionStage是Java8新增接口,用于异步执行中的阶段处理:先看接口 可以简单划分为三类: 1.在上一阶段执行结束之后,一阶段结果作为指定函数的参数执行函数产生新的结果,apply/ ...

  8. 执行文件异常报错:ImportError: attempted relative import with no known parent package

    这个问题困扰了我很久了,网上的解决方法都很一致,找来找去都是一样的解决方法,在导入包的文件和执行文件加入 1 print('__file__={0:<35} | __name__={1:< ...

  9. PHP 获取本周、今日、本月的起始时间戳

    当前周的开始时间(周一)$begintime = mktime(0, 0, 0, date('m'), (date('d') - (date('w')>0 ? date('w') : 7) + ...

  10. Linux 学习笔记04丨Linux的用户和用户组管理

    Chapter 3. 用户和用户组管理 由于Linux系统是一个多用户多任务的分时操作系统,任何一个要使用系统资源的用户,都必须首先向系统管理员申请一个账号,然后以该账号身份进入系统. 3.0 用户与 ...