万恶之源

优秀题解

用文字终究难以穷尽代码的思想

思路

每次操作都有八种选择,相当于一棵每次延申八个子节点的搜索树,故搜索应该是一种方法。而这题要求求最少步数,我们就可以想到可以试试迭代加深搜索(但其实我做它因为它是书本的习题)。再搭配一个估值函数来剪枝就很香啦。

轮换方块(操作打表)

我的原始思路十分粗暴,就是用一个二维数组来存储这个“#”图形,但是这会十分浪费空间,在写轮换操作时的代码时也很繁冗。

我学到的呢,是用一维数组来存储这个图形,也就是直接用题目的输入生成一个数组。这样进行轮换操作可能不如二维的直观,但熟悉熟悉就好吧。所以应该如何轮换呢?这其实相当于一个映射,由于每个元素在原来的图形的位置是独特的,那将原图形一维化之后,这个元素的位置也仍然是独特的。因此,我们只需要找出,原来“#”图形的某一列/行在一维数组的对应坐标就好。

但是由于数据规模不大,我们可以打表来实现,也就是事先找出某个操作需要使用的坐标。

const int index[8][7] = {  //从A-H操作变动的下标
{ 0,2,6,11,15,20,22 }, //A
{ 1,3,8,12,17,21,23 }, //B
{ 10,9,8,7,6,5,4 }, //C
{ 19,18,17,16,15,14,13 }, //D
{ 23,21,17,12,8,3,1 }, //E
{ 22,20,15,11,6,2,0 }, //F
{ 13,14,15,16,17,18,19 }, //G
{ 4,5,6,7,8,9,10 }, //H
};

可行性剪枝(估值函数)

再做这题之前我做了另外一题,HDU - 1560 - DNA sequence,这题估计的是剩余还需要处理的长度,本题估计的则是剩余还需要处理的方格(冥冥之中总感觉有相似之处)。

估计方格

因为每次轮换,最多只会引进一个目标元素(直观感受),因此,还需要处理的方格(即上文需要估计的量),就等于中心元素中,不为目标元素的元素的个数,也就是非目标元素的个数。一旦目标元素确定那计数就小菜一碟啦,但是我们怎么知道我们的目标是什么?

目标元素

我的原始思路是,开局在中心元素个数最多的即我们的目标,但是想了想说不定人家也可能一手好牌打得稀烂(结果确实存在这种情况,开始在中间最多的并不是正解),于是我最后决定还是得枚举目标,但是我总感觉开始在中间最多的越有可能是正确答案,于是按照出现的次数排序来进行枚举,搜索。(但事实证明这并没有必要,而且写出来的效果就很让人怀疑,一个问题居然要搜索三次)

做完之后我参考了一下其它题解,发现了一种更好的思路。我们完全可以作一棵没有目标的墙头草,谁最多我们就往哪倒。也就是说,我们可以计算在中间1,2,3这三个元素的个数的最大值,一旦这个计算结果等于8,我们就完成了任务!这时再去检查是谁达到了这个数字即可。(另外这样能够保证我们的结果就是最优解,按我的原始思路,很有可能出现三组解(一个搜索一个解),还需要对这三组解进行进一步的比较)

重大问题

  1. cnt()函数——估计哪个数字应该优先搜索。

在排序时思路不对,导致三个数字不能正常被排序与标记。

(我有时觉得这个函数没有用,事实上确实没有用,还徒增很多烦恼)

  1. 搜索时忘了有H这一操作。。。甚至在很后面才发现。。。

打印出每次的操作,发现只有7种操作,那就可以发现这个bug了,或者是分析出错的样例,然后分析为什么没有出现某个路径,然后再定位到拓展叶子节点的代码,应该可以发现这个bug

  1. 没有仔细审题 || 没有考虑特殊情况——No moves needed

If no moves are needed, output "No moves needed",为什么说它严重呢,因为这将导致对拍完全没有问题,但是交上去就是WA。-__-

以后做题一定要特例先行!

  1. 没有意识到1, 2, 3都有可能成为最后的答案,即使某一个数在中心的个数最少。

这个其实反而是最开始的想法,但做着做着题就认为中间数量最多的就是最后答案。。。还是考虑的不够全面啊

  1. 最后的判断依据

接着第四点,由于任何一个数都有可能成为答案,最后的判断依据应该是在某个深度下,谁的操作路径字典序最小。并且,这里面还要考虑到如果一个路径不存在,它的长度可能是最小的(string,长度为0)判断完之后,最后还得输出中心元素,这两个操作如何协调,也是一个麻烦的问题。

  1. 尝试用map储存状态

这会导致TLE==,感觉可能是状态太多了,希望以后的自己能对这个问题有更多理解,最好还能提出解决的办法。

  1. 代码十分冗杂,同时时间开销非常大,一定要学习优秀的代码

我的思路从一开始就不太正确,以至于后面花费了相当多的精力去给它修修补补。导致了这种情况的发生。

一点感悟

方向错误也不是第一次了,每当出现这种情况,我就会想起托勒密,他穷尽他的心血将地心说完善得几乎完美,但终究在一开始他便错了。但是他的错误也给后人带来的启示与借鉴,我也希望我的每一次错误都能够给日后的我或看到这篇文章的人们提供一种信息,某条路是不行的,帮助他们少走弯路,以上。

IDA*、操作打表、并行处理-The Rotation Game HDU - 1667的更多相关文章

  1. IDA 操作记录

    IDA 操作记录 1.加载文件 windows 下,用ida加载文件后,会在该文件同目录下生成几个文件,含义如下: .id0 : 二叉树数据库 .id1:    文件包含描述每个程序字节的标记 .na ...

  2. EF Codefirst 多对多关系 操作中间表的 增删改查(CRUD)

    前言 此文章只是为了给新手程序员,和经验不多的程序员,在学习ef和lambada表达式的过程中可能遇到的问题. 本次使用订单表和员工表建立多对多关系. 首先是订单表: public class Ord ...

  3. JAVASE02-Unit05: 集合操作 —— 查找表

    Unit05: 集合操作 -- 查找表 使用该类测试自定义元素的集合排序 package day05; /** * 使用该类测试自定义元素的集合排序 * @author adminitartor * ...

  4. JAVASE02-Unit04: 集合框架 、 集合操作 —— 线性表

    Unit04: 集合框架 . 集合操作 -- 线性表 操作集合元素相关方法 package day04; import java.util.ArrayList; import java.util.Co ...

  5. [转]C#操作注册表

    原文链接:http://www.cnblogs.com/txw1958/archive/2012/08/01/csharp-regidit.html 下面我们就来用.NET下托管语言C#注册表操作,主 ...

  6. [荐]使用Js操作注册表

    使用Js操作注册表 要操作注册表需要通过ActiveX控件调用WScript.shell对象,通过该对象的一些方法来操作. WshShell对象:可以在本地运行程序.操纵注册表内容.创建快捷方式或访问 ...

  7. JS:操作样式表3:内联和外链样式

    var box = document.getElementById("box"); box.style.属性;只能读取修改行内样式. //访问元素样式2,对外链样式表进行操作 do ...

  8. c++ 操作注册表

    1.       注册表简介 注册表是为Windows NT和Windows95中所有32位硬件/驱动和32位应用程序设计的数据文件,用于存储系统和应用程序的设置信息.16位驱动在Winnt (Win ...

  9. .Net操作注册表--un

    C#操作注册表 导入命名空间 Using MicroSoft.Win32;//64位系统装的64位版本

随机推荐

  1. Lombok中@Data注解的坑

    开发遇到@Data注解的大坑 如果使用@Data注解,会默认重写hashcode和equals方法 那会遇到什么问题呢? 比如说: @Data public class DataTest { priv ...

  2. 计算机网络 -- TCP/IP

    画图标准 OSI七层模型 7.应用层 作用:为用户提供软件/接口/界面 interface 协议:OICQ.HTTP.HTTPS.BT/P2P 6.表示层 作用:用于对用户数据进行数据呈现.(数据格式 ...

  3. Spring Native实战(畅快体验79毫秒启动springboot应用)

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  4. PDO操作大数据对象

    一般在数据库中,我们保存的都只是 int . varchar 类型的数据,一是因为现代的关系型数据库对于这些内容会有很多的优化,二是大部分的索引也无法施加在内容过多的字段上,比如说 text 类型的字 ...

  5. JMeter多个线程组的使用说明

    Run Thread Groups consecutively (i.e one at a time),即独立运行每个线程组(例如在一个组运行结束后启动下一个) https://help.aliyun ...

  6. java 小算法

    //鸡兔同笼 20个头 58腿 for(int a=0;a<=20;a++) { int b = 20-a; if((2*b+4*a)==58) { System.out.println(a+& ...

  7. 没想到 TCP 协议,还有这样的骚操作。。。

    大家好,我是小林. 昨晚有位读者问了我这么个问题: 大概意思是,一个已经建立的 TCP 连接,客户端中途宕机了,而服务端此时也没有数据要发送,一直处于 establish 状态,客户端恢复后,向服务端 ...

  8. [模板]多项式全家桶小记(求逆,开根,ln,exp)

    前言 这里的全家桶目前只包括了\(ln,exp,sqrt\).还有一些类似于带余数模,快速幂之类用的比较少的有时间再更,\(NTT\)这种前置知识这里不多说. 还有一些基本的导数和微积分内容要了解,建 ...

  9. openEuler 20.03/21.03 - 华为欧拉开源版(CentOS 8 华为版开源版)下载

    开始 openEuler 之旅吧 openEuler 通过社区合作,打造创新平台,构建支持多处理架构.统一和开放的操作系统,推动软硬件应用生态繁荣发展. 好玩的活动停不下来 openEuler 社区不 ...

  10. 数据库的高可用MHA实验步骤

    一.多机互信的步骤 双机互信的步骤 第一步:在master管理服务器上ssh-keygen 在master同一台管理服务器上重新开一个窗口ssh-copy-id 192.168.0.13自己给自己互信 ...