蠕虫游戏

模拟

【问题描述】

蠕虫是一个古老的电脑游戏,它有许多版本。但所有版本都有一个共同规则:操纵一条蠕虫在屏幕上转圈,并试着去避免撞到自己或障碍物。

这里我们将模拟一个简单的版本。游戏将在 50×50 的棋盘上进行,棋盘的左上角为(1,1),蠕虫在初始时是一串 20 个相连的方格。所谓连接是指方格在水平或垂直方向上相接。蠕虫开始时是水平地伸展开的,从(25,11)到(25,30)。其中(25,30)是它的头。蠕虫只能向东(E),西(W),南(S),北(N)四个方向移动,但不能向自己移动,因此在开始时向西(W)是不允许的。每次移动时,蠕虫向给定的方向移动,一次只移动一格,并且保证它的长度不变。因此只有蠕虫的头和尾所占据的方格在移动一步后被改变。注意:蠕虫的头能移动到虫尾刚刚让出的空格。

你将被给定一系列移动指令并模拟虫的移动,直到:蠕虫撞上了自己;蠕虫越出了棋盘;蠕虫成功地完成了这些指令。在前两种情况下你应当忽略剩下的指令。

【输入】

每个输入文件包含了很多组数据。每个数据占 2 行,第一行是一个整数(n<100),表示移动指令的指令数(以 n=0 表示输入结束);第 2 行包括了 n 个字符(E,W,S,N),字符之间没有空格,表示移动的指令。

【输出】

每个数据输出一行,格式为以下 3 种中的一种(m 是你要决定输出的步数):

The worm ran into itself on move m.

The worm ran off the board on move m.

The worm successfully made all m moves.

【解题过程】

我用了一个数组来记录 20 个点的坐标。贪吃蛇移动一步可以当做是尾部的点消失并出现在头部,这样处理是最方便的。

初次提交 AC。

 

直角三角形

离散化

【问题描述】

平面上给定 n 个两两不同的整数点,统计以给定的点为顶点,其直角边平行于坐标轴的直角三角形的个数。

【输入】

输入文件第一行是一个整数 n。

以下 n 行,每行是一个点的坐标。

【输出】

输出一个整数,表示统计结果。

【输入样例】

4

0 0

0 1

1 0

1 1

【输出样例】

4

【数据规模】

30%的数据满足 n≤100;

50%的数据满足 n≤1000;

100%的数据满足 0<n≤100,000,所有坐标不超过 32 位整数范围。

【解题过程】

看到 10^6 就又想到排序了。

思路很明显:枚举直角顶点是哪一个,则能构成的直角三角形的数目=横坐标与它相同的点的数目*纵坐标与它相同的点的数目。

如何统计横纵坐标相同的点的数目?先按横坐标排序,横坐标相同的点必然排在一起,统计并记录到数组中。比如对于排序后第 7 个点有 3 个点的横坐标与其相同,就令 x[7] = 3. 再按纵坐标排序,然后计算。

初次提交 AC。

 

聪明的打字员

搜索

【问题描述】

阿兰是某机密部门的打字员,出于保密的需要,该部门用于输入密码的键盘是特殊设计的,键盘上没有数字键,而只有以下六个键:Swap0, Swap1, Up, Down, Left, Right。为了说明这六个键的作用,我们先定义录入区的 6 个位置的编号,从左至右依次为 1,2,3,4,5,6。下面列出每个键的作用:

Swap0:按 Swap0,光标位置不变,将光标所在位置的数字与录入区的 1 号位置的数字(左起第一个数字)交换。如果光标已经处在录入区的 1 号位置,则按 Swap0 键之后,录入区的数字不变;

Swap1:按 Swap1,光标位置不变,将光标所在位置的数字与录入区的 6 号位置的数字(左起第六个数字)交换。如果光标已经处在录入区的 6 号位置,则按 Swap1 键之后,录入区的数字不变;

Up:按 Up,光标位置不变,将光标所在位置的数字加 1(除非该数字是 9)。例如,如果光标所在位置的数字为 2,按 Up 之后,该处的数字变为 3;如果该处数字为 9,则按 Up 之后,数字不变,光标位置也不变;

Down:按 Down,光标位置不变,将光标所在位置的数字减 1(除非该数字是 0),如果该处数字为 0,则按 Down 之后,数字不变,光标位置也不变;

Left:按 Left,光标左移一个位置,如果光标已经在录入区的 1 号位置(左起第一个位置)上,则光标不动;

Right:按 Right,光标右移一个位置,如果光标已经在录入区的 6 号位置(左起第六个位置)上,则光标不动。

当然,为了使这样的键盘发挥作用,每次录入密码之前,录入区总会随机出现一个长度为 6 的初始密码,而且光标固定出现在 1 号位置上。当巧妙地使用上述六个特殊键之后,可以得到目标密码,这时光标允许停在任何一个位置。

现在,阿兰有一个 6 位的数字密码,请编写一个程序,求出录入一个密码需要的最少的击键次数。

【输入】

仅一行,含有两个长度为 6 的数,前者为初始密码,后者为目标密码,两数间用空格隔开。

【输出】

仅一行,含有一个正整数,为最少需要的击键次数。

【输入样例】

123456 654321

【输出样例】

11

【解题过程】

丧心病狂的搜索题。

感觉 BFS 不太够,就想 A*。但是 h(x) 函数不好设计,如果 h(x) = 位置正确的数字个数,那么效果不好,对搜索没有太大的促进作用(甚至会因为优先队列的复杂度较大而劣于直接 BFS);如果 h(x) = 每个位置上的数字与目标数字的差的绝对值之和,其实是错的,因为有 Swap 操作的存在使得可以一步让两个不同的数字到正确的位置,这样不满足 h(x)<=h*(x) 的要求。

那还是直接 BFS 吧。但对于极限数据 000000 999999 基本上没希望(5s+)。

第一次提交 70 分。

后来看题解看到一个剪枝:

  • 如果当前数字已经等于目标状态中所有数字的最大值,就不执行 Up 操作;如果当前数字已经等于目标状态中所有数字的最小值,就不执行 Down 操作

后来想想这个剪枝是显而易见的,只能说做题的时候太浮躁了。

另外还要注意一下常数的优化。做这道题一般是把六个数字加上位置信息压成 7 位十进制数,而扩展状态的时候对于有些操作不必将 7 位数展开到数组里再操作,比如 Up 操作完全可以通过加上 10 的幂来改变某一位上的数字,这样会比拆分成数字再拼合成整数要快不少。

加了如上优化就能 AC 老师给的数据。

06day2的更多相关文章

  1. 二模 06day2

    很长时间没更新有意义的题目了呢,这是一套题撒,于是乎我便开心的边刷题边发题解了撒. 第一题: interval 比较好玩的一题撒, 分分钟过了, 就是模拟贪吃蛇但是没有食物(嗯,只要你判断冲突). 整 ...

随机推荐

  1. POJ 2186

    Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 22189   Accepted: 9076 Des ...

  2. NDK 编译可执行程序

    以Hello Android工程为例. 建立好工程hello-a,在jni目录下创建文件hello-a.c,文件内容如下.(注意是jni目录,使用src目录编译会出错) #include <st ...

  3. 自动化 测试框架部署(python3+selenium2)

    安装Python 从https://www.python.org/downloads/下载最新版本的Python3,请注意,是3: 需要将Python的安装目录和安装目录下的Scripts文件夹添加到 ...

  4. http://blog.163.com/zhangmihuo_2007/blog/static/27011075201392685751232/

    http://blog.163.com/zhangmihuo_2007/blog/static/27011075201392685751232/

  5. Linux问题定位工具大放送

    我们在程序定位问题时,经常不知所错,但是在linux有很多强大的工具,只要我们合理利用,一定见奇效. 主要会遇到以下问题: 1 mem高 2 cpu高 3 io高 4 网络延迟高 vargrind:h ...

  6. libprotobuf ERROR

    google/protobuf/wire_format.cc:1059] Encountered string containing invalid UTF-8 data while parsing  ...

  7. 聊聊并发(八)——Fork/Join框架介绍

      作者 方腾飞 发布于 2013年12月23日 | 被首富的“一个亿”刷屏?不如定个小目标,先把握住QCon上海的优惠吧!2 讨论 分享到:微博微信FacebookTwitter有道云笔记邮件分享 ...

  8. 嵌入式linux的学习之路[转]

    我认为的一条学习嵌入式Linux的路: 1)学习 Linux系统安装. 常用命令.应用程序安装. 2) 学习 Linux 下的 C 编程.这本书必学<UNIX 环境高级编程>.<UN ...

  9. 用SQLData读写数据库自定义类型

    如何读写自定义类型?SQLData是个很直观的解决办法 在oracle使用手册上找到了很好的资料 点击打开链接 http://docs.oracle.com/cd/B10501_01/java.920 ...

  10. Java基础复习之二:运算符,键盘录入,流程控制语句,if语句,三元运算

    1.运算符 1.1.算术运算符  +(加法有三个用法:加法,正号,字符串连接符)  -  *  /  %  ++  -- 1.1.1./ 是取商,%是取余 1.1.2.++ 与--的用法(a:作用是自 ...