声明

笔者最近意外的发现 笔者的个人网站http://tiankonguse.com/ 的很多文章被其它网站转载,但是转载时未声明文章来源或参考自 http://tiankonguse.com/ 网站,因此,笔者添加此条声明。

郑重声明:这篇记录《关于 double sort 这道题的思考》转载自 http://tiankonguse.com/ 的这条记录:http://tiankonguse.com/record/record.php?id=651

前言

前言的前言

昨天本来写好了这篇记录,可恨中间我出去打了一个电话,回来继续写,写完我想到可能session已经失效,所以我新打开一个页面,登录,然后在这个页面提交。返回了提交成功的标签,但是跳转到那篇文章时提示不存在。这个,我不能再忍受了,于是自己做了一个自动保存的功能。

首先今天写的内容将会简短,因为昨天写的好久好久,结果自动保存功能还没有实现。不过现在,时刻都在自动保存着,再也不用担心这个问题了。

首先声明这篇记录不是解题报告,只是一场我的大脑里思路的旅行。

前几天学弟学妹们有一场比赛,学弟邀请我作为技术支持者去帮忙,在那个过程中我看了几道题。

其中有两道题正常比赛没有其他人提交,于是我研究了一下。

研究的第一道就一个暴力dfs就可以过,只是可能正常比赛没人看懂题意,我看了好几个小时才看懂的。

第二道就是 double sort。

正文

题意

什么是 double sort 呢?

就以题目中的讲解例子来说说吧。

题目说对于一组数 [5; 4; 3; 2; 1], 如果只可以交换相邻的数字,要使这组数达到升序至少需要 10 步。

这个很好理解,假设一个数字要和左面的数字交换,那只有一种情况。

但是对于两组数 [5,5; 4,4; 3,3; 2,2; 1,1] 来说,也是只能交换相邻的数字。这是一个数字和左面的数字交换时就有两种情况了。

比如对于 4 可以和 第一个5交换,也可以和第二个5交换。

目标是使这两组数字达到升序。题意还说这个例子的答案是 15 ,不是 20.

然后,没然后了。

错误的题意

看完上面的题意,我有一个疑问:难道真的是要排成 [5,5; 4,4; 3,3; 2,2; 1,1] 的样子吗? 15 步可能吗?

于是我猜测可能是达到每组升序即可,比如 [4,5; 4,5; 2,3; 2,3; 1,1], 这样第一组是 [4; 4; 2; 2; 1], 第二组书[5; 5; 3; 3; 1].

于是我写了一个暴力程序,第一组样例还真跑出一个 15 的答案来。

但是第二组 答案大小比样例少了1。

既然结果不正确,那就需要把那个正确的答案的路径输出来,看看有什么不同。

结果发现最终答案应该是上下两个的差不超过2.

于是我添加了一个 fix 函数,修正这种情况。

然后三个样例都过了。

再然后就是 WA 了。

正确的题意

然后我想还是想弄明白题意再说,于是用 [3,3; 2,2; 1,1] 模拟了一下,发现真的比 [3; 2; 1] 的答案的二倍少。

这时我意识到可能目标真的是求[1,1; 2,2; 3,3]  这种情况。

暴力DFS尝试

知道了题意,数据量只是到8,于是写了一个暴力程序。

使用 "1122334455" 串的形式map 了一下。

对于5瞬间跑出答案,对于6 跑了好一会。

双向DFS搜索

直接搜太慢,那就双向搜试试。

于是写了一个双向 DFS, 结果 6也是瞬间跑出来,但是 7 怎么也出不来了。

使用逆序数剪枝双向搜索

写的虽然是双向DFS,但是其实还是暴力搜索,还没有加什么剪枝。

于是使用 逆序数剪枝, 7 十秒多跑出来了。

于是提交试试,发现 超内存,现在不是时间问题了,是内存不够的问题了。

状态压缩

内存不够就要想法节省内存,其中 map<string, string>最浪费内存。

为什么要使用 string 呢?

为了保存一个状态。

那能不能使用位数压缩状态么?

发现还真的可以。

数字是从1-8,也就是0-7 了。最少需要三位才能表示一个数字,总共需要 24位数字,3字节,long long 类型的可以。

于是修改成map<LL, LL>.

为什么要使用 map 呢?

貌似是为了记录路径,这里不需要记录路径。

于是修改成为了 set<LL> .

再次提交还是超内存。

A* 算法出世

到底是为什么会超内存呢?

因为状态太多了。

为什么状态太多了呢?

因为我们使用的暴力搜索,我们不知道哪个状态是最优解,哪个不是。

那能不能确认某个状态一定比另一个状态更优呢?

貌似可以的。

那就用优先队列吧。

于是问问学弟小堆是使用大于号还是小于号。最后自己在模板生找到了。

A*搜索的估价函数

双向搜索时曾遇到过逆序数,于是使用逆序数作为估价函数吧。

7 终于跑出来了。

但是 8 还是跑步出来。

A*搜索的另一个估价函数

逆序数这个估价函数行吗?

貌似误差太大,无效状态太多。

那能不能换一个估价函数呢?

貌似还真有一个,每个数字离自己最终的位置的距离也是一个不错的估价汗是。

那就使用这个估价函数吧。

于是把估价函数换了换,结果还是只能跑出7来。

强强联合

怎么还是跑不出 8 呢?

估价函数太弱,精度太低。

那能不能加强估价函数呢?

貌似可以的。

比如说呢?

对于逆序数,交换一次最多减少3个逆序数,最少一个。

对于相对距离,交换一次最多减少两个,最少不变。

知道了,就这个办呢。

于是使用两个估计函数,重新了程序,结果7确实跑的快乐,但是还是跑不出8来。

总结

这道题虽然没有跑出 8 来,但是收获不少。

首先这一切都是自己独立思考的,再次开发了智力。

有兴趣的人可以继续思考下去,尽量不要看解题报告。

所有代码都在这里https://github.com/tiankonguse/ACM/tree/master/hust/doublesort

参考

tiankonguse 的模板

关于 double sort 这道题的思考的更多相关文章

  1. byte在计算机中的存储方式--Double.byteValue()的输出结果思考

    先举三个栗子: 1. public static void main(String[] args) { Double d = new Double(123.56); byte b = d.byteVa ...

  2. Test Double

    我不知道Test Double翻译成中文是什么,测试替身?Test Double就像是陈龙大哥电影里的替身,起到以假乱真的作用.在单元测试时,使用Test Double减少对被测对象的依赖,使得测试更 ...

  3. Insertion Sort List——链表的插入排序

    Sort a linked list using insertion sort. 这道题跟 Sort List 类似,要求在链表上实现一种排序算法,这道题是指定实现插入排序.插入排序是一种O(n^2) ...

  4. Solution -「线段树」题目集合

    T1 无聊的数列 来自:Link flag 帖先从水题入手. 首先分析题目,它是以等差数列为原型进行的修改.等差数列一大性质就是其差分数列的值除第一项以外均相等. 于是不难想到使用差分数列进行维护. ...

  5. NOIP模拟赛-旅行者问题 解题报告

    旅行者问题 [问题描述] lahub是一个旅行者的粉丝,他想成为一个真正的旅行者,所以他计划开始一段旅行.lahub想去参观n个目的地(都在一条直道上).lahub在起点开始他的旅行.第i个目的地和起 ...

  6. UVa 10025: The ? 1 ? 2 ? ... ? n = k problem

    这道题仔细思考后就可以得到比较快捷的解法,只要求出满足n*(n+1)/2 >= |k| ,且n*(n+1)/2-k为偶数的n就可以了.注意n==0时需要特殊判断. 我的解题代码如下: #incl ...

  7. POJ3304 Segments 【线段直线相交】

    题意: 给出n条线段两个端点的坐标,问所有线段投影到一条直线上,如果这些所有投影至少相交于一点就输出Yes!,否则输出No!. 思路: 计算几何.这道题要思考到两点: 1:把问题转化为是否存在一条直线 ...

  8. 2018-2019-20172329 《Java软件结构与数据结构》第九周学习总结

    2018-2019-20172329 <Java软件结构与数据结构>第九周学习总结 教材学习内容总结 <Java软件结构与数据结构>第十五章-图 一.图及无向图 1.图的相关概 ...

  9. 【HNOI2008】玩具装箱

    P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1...N的N件玩具,第i件玩具 ...

随机推荐

  1. windows下gitbook与开源中国码云关联,以及如何gitbook转pdf

    gitbook能够很方便的和github关联,实现团队协作的效果.可是github私有库需要付费.但是开源中国码云能够建私有库,于是考虑将gitbook关联码云,折腾了一番后,能够可视化的关联,后面就 ...

  2. C# 代码 获取桌面路径

    Environment.GetFolderPath(Environment.SpecialFolder.MyComputer); // // 摘要: // 获取由指定枚举标识的系统特殊文件夹的路径. ...

  3. Android 打开URL中的网页和拨打电话、发送短信功能

    拨打电话需要的权限 <uses-permission android:name="android.permission.CALL_PHONE"/> 为了省事界面都写一起 ...

  4. 201621123023《Java程序设计》第4周学习总结

    一.本周学习总结 1.1 写出你认为本周学习中比较重要的知识点关键词 继承.多态.覆盖.重载 1.2 尝试使用思维导图将这些关键词组织起来.注:思维导图一般不需要出现过多的字. 二.书面作业 1. 面 ...

  5. PLSQL基本操作手册

    第1章  用PLSQL连接Oracle数据库 PLSQL只能用来连接Oracle数据库(不象PB还可以连接JDBC.ODBC),所以必须首先安装并配置Oracle客户端. §1.1 初次登录PLSQL ...

  6. 自己实现一个shell

    用C实现一个简单的交互式shell,要求:当用户输入一行命令时,识别程序名和参数并调用适当的exec函数执行程序,等待执行完成后给出提示符. exec函数实际上是六种以exec开头的函数,统称exec ...

  7. [独家] Adobe Flash 直接复制元件不改变原元件

    正在考网页高级考证,然后会需要做Adobe Flash相关操作.在网上看了下,基本都是错误的.于是,自己研究解决该问题. 首先,你需要更改元件不改变原文件是不可能的. 所以: 1.你需要对原元件所在的 ...

  8. svn提交新文件夹同时不需要更新全部上级目录

    关于svn的指定目录指定位置更新:当在提交了新建的目录后可以使用 a)  在需要更新的上级目录上单击右键 在延伸菜单中选择 b)  弹出对话框中选择,check repository c)  新添加的 ...

  9. Ionic2使用百度地图API(JS)出现白屏解决方案

    最近自学ionic2,写了一个内嵌百度地图JS的demo,实际跑起来之后出现了大家常见的白屏问题.. 最初的实现是这样的: 首先主页内嵌了一个百度地图插件 <div id="Bmap& ...

  10. java 数字转 字符串 互相转换

    各种数字类型转换成字符串型:   String s = String.valueOf( value); // 其中 value 为任意一种数字类型.   字符串型转换成各种数字类型:   String ...