蠕虫游戏

模拟

【问题描述】

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

这里我们将模拟一个简单的版本。游戏将在 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 老师给的数据。

最新文章

  1. Discuz NT 架构剖析之Config机制
  2. Android之Dialog详解
  3. 《c语言全局变量的用法》
  4. javac 不是内部或外部命令
  5. 最常用的MySQL命令语句
  6. POJ2632——Crashing Robots
  7. jqgrid使用简单记录
  8. Linux进程间通信——信号集函数
  9. 基于FT5x06嵌入式Linux电容触摸屏驱动
  10. 二、vue之 使用vscode配置
  11. EF CodeFirst系列(8)--- FluentApi配置单个实体
  12. lunx中部分命令总结
  13. Python map,filter,reduce函数
  14. laravel 视图
  15. java 程序运行过程 简介
  16. Zabbix-2.X/3.X监控工具监控Redis以及zabbix Redis监控模板下载
  17. 20135220谈愈敏Blog4_系统调用(上)
  18. ThinkPHP框架学习(一)
  19. Oracle学习笔记:实现select top N的方法
  20. web项目启动执行方法

热门文章

  1. iOS多线程的初步研究(四)-- NSTimer
  2. sql server 数据库 数据DateTime 转mysql
  3. JavaWeb开发好资料
  4. light oj 1205 - Palindromic Numbers 数位DP
  5. 传说中的WCF(5):数据协定(a)
  6. java for循环的几种写法
  7. QWidget的六个刷新函数(居然有QWidget::erase函数,且并不产生绘制事件)
  8. http://www.cnblogs.com/wzh206/archive/2010/03/21/1691112.html
  9. 实用Linux命令,不求最全但求实用-------磁盘使用情况du,df
  10. ubuntu 12.04安装vncserver