PAT 1031-1040 题解

早期部分代码用Java实现。由于PAT虽然支持各种语言,但只有C/C++标程来限定时间,许多题目用Java读入数据就已经超时,后来转投C/C++。浏览全部代码:请戳

本文谨代表个人思路,欢迎讨论;)

1031. Hello World for U (20)

题意

将给定的字符串打印出U型。

比如给定helloworld,打印出


h  d
e  l
l  r
lowo

设定左边的字符个数为n1,底边字符个数为n2,右边字符个数为n3。需要满足 n1 = n3 = max {k|k <= n2 for all 3 <= n2 <= N} with n1 + n2 + n3 -3 = N.

分析

简单模拟题。

1032. Sharing (25)

题意

为了节省存储空间,单词使用链表实现。比如对于loadingbeing两个单词,有如下存储结构:

word1 : -> [l] -> [o] -> [a] -> [d]  
                                    \
                                      [i] -> [n] -> [g] -> null
                                    /
word2 : -> [b] -> [e] -------------

输入中,指定了两个单词的首字符的地址,并给出了N (<= 10^5)个节点,每个节点包含:物理地址(5位的正整数),实际存储的字符以及指向的下一个节点的地址。NULL的地址是-1. 要求找到两单词的的公共后缀开始的地址,如果没有,则输出-1.

分析

既然是单词,它的长度应该是有限的,也就是链表不会出现环这种情况(实际上这里的处理方式对于有环无环都适用)。对第一个单词链表做遍历,对爬过的节点做好标记。第二个单词链表也同样做标记,一旦遇到已经标记过的节点,则该节点就是结果。

需要注意一点:直接使用map做节点的存储最后一个case会超时。而鉴于5位正整数的数据量,可以直接使用数组,用空间换时间。

1033. To Fill or Not to Fill (25)

题意

高速路从A地到B地,路途有许多加油站,每个加油站的油价不一样,要求计算一个最优方案,使得以最便宜的开销跑完全程。

分析

用贪心算法,理清贪心算法的策略:

  • 1.从A加油站出发,在能行走的最大范围内,如果有比A站汽油更便宜的B站,则保证在A站点的加油量刚好满足能到达B站点;如果没有比A站汽油更便宜的站,则在A加满车油行走到【从A能走出的范围内】油价【最便宜】的站上,再行计算。
  • 2.从A加油站出发,在能行走的最大范围内,如果没有其他站点,则A.dist + 一次最大的行走距离 为impossible情况下的最大站点。

    注意有个陷阱:如果没有距离为0的加油站,则无法行驶。

1034. Head of a Gang (30)

题意

『gang』翻译过来是『一伙人』。gang的定义是一羣人,至少有3个人,这羣人中每个人之间都通过通话相连,且整个羣体的通话时长超过一个阈值。整个gang的团体中,拥有的电话时长最长的人就是头目了。

题目给定了gang的阈值K,以及N个通话记录,每条记录包括主叫人、被叫人以及通话时间。要求计算出有几个gang,并按照gang的头目的字母顺序排序输出头目和其中成员数量。

分析

本题使用dfs求解比较方便。dfs能简单的实现状态值的记录,比如当前的gang的成员数量和权重,如果使用并查集,则相对复杂。

需要注意的坑点:如果建立邻接表时,每个通话记录都在两人头上计算了时间积累的,那么在判定gang的权重值是否低于阈值的时候,需要对阈值乘以2。

1035. Password (20)

题意

给定多个字符串,按要求替换其中的某些特殊字符,并按原顺序输出。如果字符串中没有需要修改的字符,则不舒服该字符串。

分析

简单的hash实现。

1036. Boys vs Girls (25)

题意

输入是一批学生的成绩,要求找出其中男生最低的成绩和女生最高的成绩,求其间的差值。如果无法计算,则输出NA.

分析

简单模拟题。

1037. Magic Coupon (25)

题意

背景是火星上的神奇的购物券购物策略:每张购物券上有一个整数,可正可负,商店里商品的标价也是一个整数,可正可负的。如果用正值购物券购买正值商品,则可获利两者之积;如果以负值购物券购买负值商品,也可获利两者之积;但其他情况,则会亏损。比如用面值为2的购物券购买面值为3的商品,获利6,用面值为-5的购物券购买面值为-9的商品,获利45,但如果用面值为2的购物券购买面值为-3的商品,则亏损6

给定一组数量为NC购物券面值和一组数量为NP的商品面值,1<= NC , NP <= 10^5,要求计算能获利的最大值。

分析

同号相乘可获利,异号相乘会亏损。要使获利最大,使用贪心思想计算。实际上,不需要用完购物券或者买完商品,所以只需要将同号的数值乘积算出即可,没有更复杂的情况。

1038. Recover the Smallest Number (30)

题意

给定N(<= 10000)个不超过8位的非负整数,要求将其按某个顺序拼接为一个数,使其值最小。

分析

容易简单的以为使用字典序排列拼接,实际上有一个特殊的拼接情况需要考虑。

比如数据32 321 3214,这是按字典序排列的,但实际上这并不是最小的拼接方式,最小的拼接方式是:321 3214 32

比较这个实例,不难找到最小拼接的排序规律:

  • 1.两个字符串做比较时,如果其中一个字符串(a)是另一个字符串(ab)的前缀串,则需要将较长字符串(ab)除去前缀串的部分(b)与较短字符串(a)继续递归比较。比如,321和32,需要拿1和32做比较。又比如323和32比较,第一次拿3和32比较,第二次拿3和2按字典序比较。
  • 2.其他情况按字典序比较。

另外需要注意的一个坑是:如果没有数据,则输出0。

1039. Course List for Student (25)

题意

给出K(<=2500)门课程,每门课程有Ni(<=200)名学生,学生编号为四位字符串,前三位为小写英文字母,后一位是数字。另给出N个需要查询的学生编号。

要求列出对应查询编号学生的课程。如果有多个课程,需要按升序输出。

分析

这个题是个倒排索引的实现。不过在时间上卡的比较严。

使用最简单的思路:map students倒排索引,在没有输出排序的课程列表时最后一个case已经超时;优化:将学生姓名的hash为int,减免了string的匹配过程,还是超时(map本身用红黑树实现,效率并不是特别高,还需要对每组数据进行排序),只能改变使用map的方式。

最终AC的解法是:

  • 构建一个从学生编号字符串到int值的hash函数,在读入学生编号后,hash到int值做处理。
  • 不适用map结构,根据学生姓名的限制,设定一个vector<int> st[26*26*26*10]的数据结构,读入时直接倒排索引插入。

1040. Longest Symmetric String (25)

题意

给定一个字符串,要求输出最长的连续对称子串的长度。比如给定字符串为Is PAT&TAP symmetric?,其中最长对称子串为s PAT&TAP s,所以输出结果11.

分析

这个题就是典型的Java实现timeout,而Cpp实现轻松过的类型。需要注意两点:

  • 1.有两种对称情况,一种形如aba,一种形如abba
  • 2.循环遍历的过程,以index为对称中心向两边扩散比较编码实现简单也更高效。

另外,C读入一整行数据到char数组的方法可以用gets(s);

原文地址:http://biaobiaoqi.github.com/blog/2013/07/31/pat-1011-1020-solutions/
 版权声明:自由转载-非商用-非衍生-保持署名| Creative Commons BY-NC-ND 3.0

点赞