今天把百度2016/2017秋招剩余的4星题目,以及少部分有难度或者比较有趣味的3星题目来一块儿分析下,因此此次就来个合集了(共包含了4个题目),整体来看题目比较简单,因此分析也会写得相对简略一些。尽管题目比较简单,可是实际编写的时候仍是会遇到一些问题,建议本身动手尝试解答。node
<题目来源: 百度2017秋招 原题连接-可在线提交(赛码网)>数据结构
有一个nm的格子图,每一个格子最多与其周围的四个相邻,不相邻的格子之间互相不可达。设一个46的格子图坐标以下:
_ 123456
1 ######
2 ######
3 ######
4 ######
则(2,3)的格子与(1,3),(3,3),(2,2),(2,4)相邻。
格子与格子之间存在特殊的墙,阻止两个相邻的格子的移动。若(2,3)存在一堵左侧的墙,则(2,3)将没法直接到达(2,2),但(2,2)仍能到达(2,3)。
现给出每一个格子周围墙的状况,求从给定的点(S,T)出发,到达每个格子最少通过多少个格子。app
这个题目须要求到地铁每个格子的最短距离,显然咱们须要从起点不断地向外扩展,不断的尝试移动一步能够到哪些距离,移动两步能够到哪些距距离...如此移动下去直到全部的格子都被到达,咱们能够确保咱们到达每个格子都是最短的距离。ide
其实这个正是咱们BFS(广度优先搜索的思想),并且这个题目十分适合做为BFS的入门题目。咱们首先为按广度优先的方式,遍历这个地图设置一个方向增量,以便咱们去每次向4个方向扩展(若是没有围墙的状况)spa
dirs = [[-1, 0, 0], [1, 0, 1], [0, -1, 2], [0, 1, 3]]设计
外层列表表示其有4个方向,其中内层列表的含义:
第1位表示要移动到的这个方向,当前x坐标须要增长(减小)的单位
第2位宝石要移动到的这个方向,当前y坐标须要增长(减小)的单位
第3位表示判断这个方向是否存在围墙的二进制位在从低位开始计数的第几位code
从起点开始扩展,设置一个队列来存储到达的那些位置以及距离,每次扩展后的x,y坐标和距离都放入这个队列,而后再从队列中取出,不断进行扩展,要主要判断边界和围墙的状况。orm
让然,这个题目也能够按最短路径的方式,上下左右相邻的两个点只要没有围墙,就建一条边,而后从起点求一次单源点最短路径便可。xml
const_x = 0 const_y = 1 const_wall_bit = 2 dirs = [[-1, 0, 0], [1, 0, 1], [0, -1, 2], [0, 1, 3]] def bfs(map_info, dist, n, m, s, t): que = [(s, t)] dist[s][t] = 0 while len(que): cur_x, cur_y = que.pop(0) for d in dirs: if 1 <= cur_x + d[const_x] <= n and 1 <= cur_y + d[const_y] <= m and \ not map_info[cur_x][cur_y] & (1 << d[const_wall_bit]) and \ dist[cur_x + d[const_x]][cur_y + d[const_y]] == -1: dist[cur_x + d[const_x]][cur_y + d[const_y]] = dist[cur_x][cur_y] + 1 que.append((cur_x + d[const_x], cur_y + d[const_y])) def main(): t_cases = int(raw_input()) for t_case in range(1, t_cases + 1): temp = raw_input().split(' ') n, m, s, t = int(temp[0]), int(temp[1]), int(temp[2]), int(temp[3]) map_info = [[0 for i in range(m + 2)] for i in range(n + 2)] for i in range(1, n + 1): line = raw_input().split(' ') for j in range(1, m + 1): map_info[i][j] = int(line[j - 1]) dist = [[-1 for i in range(m + 2)] for i in range(n + 2)] bfs(map_info, dist, n, m, s, t) print 'Case {}:'.format(t_case) for i in range(1, n + 1): for j in range(1, m + 1): print dist[i][j], print if __name__ == '__main__': main()
<题目来源:百度2017秋招 原题连接-可在线提交(赛码网)>队列
可扩展标记语言(英语:Extensible Markup Language,简称:XML),是一种标记语言。
XML 设计用来传送及携带数据信息,不用来表现或展现数据,HTML语言则用来表现数据,因此 XML 用途的焦点是它说明数据是什么,以及携带数据信息。
例如,下面是一段 XML 标签。
<recipe> <recipename>Ice Cream Sundae</recipename> <ingredlist> <listitem> <quantity>3</quantity> <itemdescription>chocolate syrup or chocolate fudge</itemdescription> </listitem> <listitem> <quantity>1</quantity> <itemdescription>nuts</itemdescription> </listitem> <listitem> <quantity>1</quantity> <itemdescription>cherry</itemdescription> </listitem> </ingredlist> <preptime>5 minutes</preptime> </recipe>
在这个问题中,你须要在给定的文本 XML 中,查找出给定模式 XML 的全部出现的位置。文本 XML 中的每一个标签按照出现的顺序编号,根节点的编号为 1,例如上面的第一个 <listitem> 标签的编号为 4,文本和模式标签有且仅有一个根节点,输出每组匹配中,模式 XML 的根节点标签在文本 XML 中的编号。
模式是相似这样的字符串:<listitem><quantity></quantity></listitem>
这题目是要处理xml并匹配模式。这类题目首先咱们须要能方便的访问它的每个节点,XML本深就是一种树形结构,显然咱们应该先建树,采用tree-list的形式,而且按照层次的顺序为其标号。为了建树和描述这个xml,咱们数据结构设计以下:
class TreeType: def __init__(self, lab='', father=None, num=0): self.num = num self.lab = lab self.father = father self.son_list = []
其中num表示编号,lab是xml的标签,father是父亲节点,方便咱们建树时,遇到</>返回到其父节点。son_list是当前节点的全部的子节点。
为了方便处理,先建个虚拟的根节点(尽管本题说明了xml只有一个根节点,这样作的好处是,你每一个节点均可以调用统一的插入或者返回上层节点的操做,不须要特别处理一开始的根节点),建树按行扫描xml,遇到<>就为当建立一个新的节点,而且添加描述信息,而后将当前节点指向这个新建的节点。若是遇到</>就退回到其父节点便可。当退回到虚拟的根节点的时候,代表xml读取完成(这也是简历虚拟根节点的好处)。
建树完成后,咱们对这棵树进行dfs,按深度去查找是否存在题目给定的模式。须要注意到下面的这种特殊的状况:
<a> <b> <c></c> <c></c> <c></c> </b> </a>
若是模式为
<b><c></c></c>,
咱们DFS的时候要注意重复识别的问题,这样的模式题目只算出现一次。此外,不要从本题的页面直接复制输入样例。
import sys const_self = 1 class TreeType: def __init__(self, lab='', father=None, num=0): self.num = num self.lab = lab self.father = father self.son_list = [] def parse_line(line): labs = [] t_lab = [] lab_f = False for ch in line: if ch == '<': lab_f = True if lab_f: t_lab.append(ch) if ch == '>': lab_f = False labs.append(list(t_lab)) t_lab[:] = [] return labs def new_lab_to_tree(cn, r, cnt): node = TreeType(r, cn, cnt) cn.son_list.append(node) return node def finish_lab(cn, r): return cn.father def dfs(cn, mode, state, first_p, matched_p, fi): lab = ''.join(cn.lab) next_s = state if lab == ''.join(mode[state]): next_s += 1 else: next_s = 0 if next_s == 1: first_p = cn.num if next_s >= len(mode) / 2 and not fi: if not len(matched_p) or first_p != matched_p[-1]: matched_p.append(first_p) fi = True for son in cn.son_list: dfs(son, mode, next_s, first_p, matched_p, fi) def main(): node_cnt = 0 current_node = TreeType('', None, node_cnt) xml = [] while True: line = map(str, sys.stdin.readline().strip().split('\n'))[0] labs = parse_line(line) xml.append(labs) for lab in labs: if ''.join(lab).startswith('</'): current_node = finish_lab(current_node, lab) # r is used for verify else: node_cnt += 1 current_node = new_lab_to_tree(current_node, lab, node_cnt) if current_node.num == 0: break mode = parse_line(map(str, sys.stdin.readline().strip().split('\n'))[0]) matched_p = [] dfs(current_node, mode, 0, 0, matched_p, False) print len(matched_p) for p in matched_p: print p, if __name__ == '__main__': main()
<题目来源:百度2017秋招 原题连接-可在线提交(赛码网)>
有一个含n字节的连续内存区域可能存在问题,工程师手中有一种检查软件,软件每次运行能够检查一段连续内存区间。因为检查的区间长度越长,要花费的时间就越多,所以工程师但愿可以在运行最多m次程序的状况下,每次检查的区间长度最大值最小,且检查的区间的并集包含了全部出现的"1"。现给出内存的状况(0表明该字节不须要检查,1表明该字节须要检查),求最小的区间最大长度。
须要注意到这类题目的重要信息:最小的区间最大长度,仔细阅读这个题目以后咱们会发现,若是咱们从正面入手考虑,会考虑比较多的状况,尤为是既要考虑到这个最小的区间,又要考虑到使得其长度尽量的大,难度比较大。另外观察到,这个题目的答案是一个已知的区间,答案的范围不外乎就是整个内存区域的长度,或者在m足够大的状况,咱们能够为每一个“1”单独检查一次,这时的答案是1。
因为答案是连续且单调递增的,那么咱们能够考虑二分枚举全部的答案,剩下的问题就是如何验证这个答案是否正确了。显然咱们从内存区域的一个方向开始后,碰到1就须要检查,这个时候,按长度检查便可。当前长度的区间检查完后扫描内存,碰到1就继续及检查,若是超过m次,且还没完成检查,那么证实这个答案不可行,咱们就缩小了答案的范围。
import sys def test_scan(l_segment, i_segment_len, i_len, i_lim): i_cur_lf = 0 i_use = 0 b_allzero = True for i in range(i_segment_len): if '1' == l_segment[i]: b_allzero = False if not i_cur_lf: i_use += 1 i_cur_lf = i_len if i_cur_lf: i_cur_lf -= 1 if i_use <= i_lim: if i_len > 0 or (0 == i_len and b_allzero): return True return False if __name__ == '__main__': i_test_case = int(raw_input()) for scr in range(i_test_case): l_line = raw_input().split() i_segment_len = int(l_line[0]) i_exe_lim = int(l_line[1]) l_segment = list(raw_input()) i_top = i_segment_len i_bot = 0 while i_top >= i_bot: i_mid = (i_top + i_bot) / 2 if test_scan(l_segment, i_segment_len, i_mid, i_exe_lim): i_res = i_mid i_top = i_mid - 1 else: i_bot = i_mid + 1 print 'Case ' + str(scr + 1) + ': ' + str(i_res)
<题目来源: 百度2017秋招 原题连接-可在线提交(赛码网)>
小A、小B、小C三人正组队参加现场赛。小A刚过了一道大模拟,伸出手想看看几点了,却发现本身没有带表,队友也没有带,由于你们平时是用手机看的。小A发现现场有一个电子显示屏上面有时间。
电子显示屏是一个7100的点阵,当前时间为一个729的矩阵,在显示屏上左右滚动,详见样例
数字0~9分别用7*6的矩阵表示以下
遗憾的是,小A眼睛高度近视,须要你念出时间给他听...
因此如今给你一个这样的点阵,输出当前时间。
输入
多组输入数据,第一行是数据组数T(T≤1440)。
接下来是T组数据,每组数据是一个7100的点阵。输入数据保证其中存在合法的729的点阵,详见样例。
输出
对每组数据输出一行答案,该行中输出“Case #k: result”(对应第k组数据,冒号后有空格),result为当前时间h:m。
这类题目主要难点在于字符串的处理,如何设计数据结构去存储这个样的一个点阵,而后是要利于咱们对这个点阵进行处理。
首先,咱们考虑如何识别点阵数字,其实这个里面有一些特征,咱们能够耐心的去找出来,咱们能够从须要数目多的开始入手:例如"8",咱们确保3个点的有无""就能够识别。可是,整体我以为仍是比较麻烦。容易出错,还不太好排除问题。
个人方法就比较暴力,可是颇有效:把每一个数字的76的点阵存在代码里,取出7100点阵中的每一个数字,而后逐行按字符串比较便可。
剩下最后一个须要解决的问题是如何定位的问题,由于这个数码从哪一列开始,并非固定的。观察后,咱们发现经过定位“:”而后计算小时的开始,和分钟的开始很方便,每一个数码相对于":"的位置[-14, -7, 2, 9],至此这个问题也就完全解决了。
import sys const_board_row = 7 const_board_col = 100 template = [['******', '* *', '* *', '* *', '* *', '* *', '******'], [' *', ' *', ' *', ' *', ' *', ' *', ' *'], ['******', ' *', ' *', '******', '* ', '* ', '******'], ['******', ' *', ' *', '******', ' *', ' *', '******'], ['* *', '* *', '* *', '******', ' *', ' *', ' *'], ['******', '* ', '* ', '******', ' *', ' *', '******'], ['******', '* ', '* ', '******', '* *', '* *', '******'], ['******', ' *', ' *', ' *', ' *', ' *', ' *'], ['******', '* *', '* *', '******', '* *', '* *', '******'], ['******', '* *', '* *', '******', ' *', ' *', '******']] def compare_dig(board, col_begin, col_end): for i in range(10): match_f = True for row in range(7): # print ''.join(board[row][col_begin:col_end + 1]) if ''.join(board[row][col_begin:col_end + 1]) != ''.join(template[i][row]): match_f = False break if match_f: return i return -1 def main(): test_cases = map(int, sys.stdin.readline().strip().split())[0] for test_case in range(1, test_cases + 1): board = [['' for i in range(const_board_col)] for j in range(const_board_row)] for i in range(const_board_row): board[i] = map(str, sys.stdin.readline().split('\n'))[0] # local divide tag for i in range(const_board_col): cnt = 0 for j in range(const_board_row): if board[j][i] == '*': cnt += 1 if cnt == 2 and board[2][i] == '*' and board[4][i] == '*': dv_tag_col = i break dg_local = [-14, -7, 2, 9] rs = [] for i in range(4): rs.append(compare_dig(board, dv_tag_col + dg_local[i], dv_tag_col + dg_local[i] + 5)) hh = rs[0] * 10 + rs[1] mm = rs[2] * 10 + rs[3] print ('Case #{}: {}:{}').format(test_case, hh, mm) if __name__ == '__main__': main()