蓝桥杯训练营第二周作业
1. 带分数
问题描述
100 可以表示为带分数的形式:100 = 3 + 69258 / 714。
还可以表示为:100 = 82 + 3546 / 197。
注意特征:带分数中,数字1~9分别出现且只出现一次(不包含0)。
类似这样的带分数,100 有 11 种表示法。
输入格式
从标准输入读入一个正整数N (N<1000*1000)
输出格式
程序输出该数字用数码1~9不重复不遗漏地组成带分数表示的全部种数。
注意:不要求输出每个表示,只统计有多少表示法!
样例输入1
100
样例输出1
11
样例输入2
105
样例输出2
6
num = int(input()) # 获取要计算的值
def check(N, n, m):
ls = []
while N > 0:
ls.append(N % 10)
N //= 10
while n > 0:
ls.append(n % 10)
n //= 10
while m > 0:
ls.append(m % 10)
m //= 10
ls.sort()
if ls != [i for i in range(1, 10)]:
return False
else:
return True
count = 0
for N in range(1, num):
for n in range(1, 1000):
m = (num - N) * n
if check(N, n, m):
count += 1
print(count) # 输入100时,输出11,输入105时输出6
2. 李白打酒
题目描述
话说大诗人李白,一生好饮。幸好他从不开车。
一天,他提着酒壶,从家里出来,酒壶中有酒2斗。他边走边唱:
无事街上走,提壶去打酒。
逢店加一倍,遇花喝一斗。
这一路上,他一共遇到店5次,遇到花10次,已知最后一次遇到的是花,他正好把酒喝光了。
请你计算李白遇到店和花的次序,可以把遇店记为a,遇花记为b。则:babaabbabbabbbb 就是合理的次序。像这样的答案一共有多少呢?请你计算出所有可能方案的个数(包含题目给出的)。
def fun(wine, shop, flo):
global count
if shop > 0:
fun(wine*2, shop-1, flo)
if flo > 0:
fun(wine-1, shop, flo-1)
if shop == 0 and wine == 1 and flo == 1:
count += 1
return count
count = 0
fin = fun(2, 5, 10)
print(fin) # 14
3. 第39级台阶
题目描述:
小明刚刚看完电影《第39级台阶》,离开电影院的时候,他数了数礼堂前的台阶数,恰好是39级!
站在台阶前,他突然又想着一个问题:
如果我每一步只能迈上1个或2个台阶。先迈左脚,然后左右交替,最后一步是迈右脚,也就是说一共要走偶数步。那么,上完39级台阶,有多少种不同的上法呢?
输出格式:
输出一个整数
# 动态规划 O(1)
dp = [[0, 0] for i in range(40)] # 左边值代表阶梯数,右边值表示左(1)右(0)脚
dp[1][0] = 0 # 整体表示达到当前阶梯时的方案个数
dp[1][1] = 1
dp[2][0] = 1
dp[2][1] = 1
for n in range(3, 40):
dp[n][1] = dp[n-1][0] + dp[n-2][0]
dp[n][0] = dp[n-1][1] + dp[n-2][1]
print(dp[39][0]) # 51167078
4. 穿越雷区
题目描述
已知的地图是一个方阵,上面用字母标出了A,B区,其它区都标了正号或负号分别表示正负能量辐射区。它必须交替地穿越正能量辐射区和负能量辐射区才能保持正常运转,否则将报废。
例如:
A + - + -
- + - - +
- + + + -
+ - + - +
B + - + -
坦克车只能水平或垂直方向上移动到相邻的区。
数据格式要求:
输入第一行是一个整数n,表示方阵的大小, 4<=n<100
接下来是n行,每行有n个数据,可能是A,B,+,-中的某一个,中间用空格分开。
A,B都只出现一次。
要求输出一个整数,表示坦克从A区到B区的最少移动步数。
如果没有方案,则输出-1
例如:
用户输入:
5
A + - + -
- + - - +
- + + + -
+ - + - +
B + - + -
则程序应该输出:
10
资源约定:
峰值内存消耗 < 512M
CPU消耗 < 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意: main函数需要返回0
注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
注意: 所有依赖的函数必须明确地在源文件中 #include , 不能通过工程
# 米奇妙妙屋
import sys
# 方阵大小
n = int(input())
# 起点,终点坐标
Ax, Ay = 0, 0
# 移动方向上,右,下,左
direction = [[-1, 0], [0, 1], [1, 0], [0, -1]]
# 最小步数,初始为一个最大值
step = sys.maxsize
# 存储地雷地图,多申请
map_list = [[''] * (100 + 5) for i in range((100 + 5) + 1)]
# 地图上每个点的访问状态
map_visit = [[False] * (100 + 5) for j in range((100 + 5) + 1)]
# 判断
def judge(x, y, new_x, new_y):
# 如果越界了
if new_x < 1 or new_x > n or new_y < 1 or new_y > n:
return False
# 如果新移动的点与上一个点的取值相同
if map_list[x][y] == map_list[new_x][new_y]:
return False
# 其余情况
return True
# 深度搜索
def dfs(x, y, cnt):
"""
:param x: 当前所在点的x坐标
:param y: 当前所在点的y坐标
:param cnt: 当前所走的步数
:return:
"""
global step
# 边界
# 到达终点
if map_list[x][y] == 'B':
# 更新最小步数
step = min(step, cnt)
return
# 向上,右,下,左四个方向进行试探
for i in range(4):
new_x = x + direction[i][0]
new_y = y + direction[i][1]
# 深度搜索
if not map_visit[new_x][new_y]:
if judge(x, y, new_x, new_y):
map_visit[new_x][new_y] = True
dfs(new_x, new_y, cnt + 1)
# 回退
map_visit[new_x][new_y] = False
# 读入地图
for i in range(1, n + 1):
temp_s = input().split()
for j in range(1, len(temp_s) + 1):
map_list[i][j] = temp_s[j - 1]
# 起点
if temp_s[j - 1] == 'A':
Ax = i
Ay = j
map_visit[Ax][Ay] = True
dfs(Ax, Ay, 0)
if step != sys.maxsize:
print(step)
else:
print(-1)
5. 迷宫
题目描述
下图给出了一个迷宫的平面图,其中标记为 1 的为障碍,标记为 0 的为可 以通行的地方。
010000
000100
001001
110000
迷宫的入口为左上角,出口为右下角,在迷宫中,只能从一个位置走到这 个它的上、下、左、右四个方向之一。 对于上面的迷宫,从入口开始,可以按DRRURRDDDR 的顺序通过迷宫, 一共 10 步。其中 D、U、L、R 分别表示向下、向上、向左、向右走。 对于下面这个更复杂的迷宫(30 行 50 列),请找出一种通过迷宫的方式, 其使用的步数最少,在步数最少的前提下,请找出字典序最小的一个作为答案。 请注意在字典序中D<L<R<U。(如果你把以下文字复制到文本文件中,请务 必检查复制的内容是否与文档中的一致。在试题目录下有一个文件 maze.txt, 内容与下面的文本相同)
答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一 个字符串,包含四种字母 D、U、L、R,在提交答案时只填写这个字符串,填 写多余的内容将无法得分
# 已然蒙圈,以下借鉴大神
import collections
#导入collections库,会用到其中deque模块(队列)
f=open("maze.txt","r")
#打开文件(该文件和py文件在同一目录下面,否则应当改成文件的绝对路径)
s=f.readlines()
#读取文件的所有行,形成一个列表,每一行为一个元素
#---------------------------------------------------------
position={}
#建立坐标位置对应0/1的字典
#先建围墙的坐标,由于1代表障碍,所以围墙设为1
for y_wall in range(0,32):
position[(0,y_wall)]='1'
position[(51,y_wall)]='1'
for x_wall in range(0,52):
position[(x_wall,0)]='1'
position[(x_wall,31)]='1'
y=1
#y位置的初始值
for y_position in s:
#遍历s中的每一行
for xy_index in range(len(y_position)-1):
#xy_index:0,1,2...49
position[(xy_index+1,y)]=y_position[xy_index]
#读取每一个0/1位置的坐标,将其加入到字典中去
y=y+1
#每读取一行之后,下一行y位置的值加1
#上面程序运行之后,01文件的每个点的坐标建立完毕,存储在字典position中
#---------------------------------------------------------
#下面开始对每个点开始搜索并且开始记录
m_deque=collections.deque()
#创建队列
start=(1,1)
end=(50,30)
checked_position=[]
#记录检查过的点的坐标信息的一个列表
m_deque.append(start)
#把起点加入到搜索队列中
while m_deque:
#只要队列不空,就继续搜索
to_check_position=m_deque.popleft()
#把队列的第一个位置拿出来检查
if to_check_position not in checked_position:
#如果这个点(坐标)没有被检查过
if to_check_position==end:
print("ok!")
break
#如果这个点为出口的点的坐标,那么输出ok,同时循环结束
else:
#否则循环继续
checked_position.append(to_check_position)
#记录已经检查过的坐标
up_position=(to_check_position[0],to_check_position[1]-1)
down_position=(to_check_position[0],to_check_position[1]+1)
left_position=(to_check_position[0]-1,to_check_position[1])
right_position=(to_check_position[0]+1,to_check_position[1])
#返回正在被检查的坐标的上下左右点位置的坐标
#不能用elif!!!!!!!!!!!!只能每个都是if
if position.get(up_position)=="0" and up_position not in checked_position:
m_deque.append(up_position)
#如果这个上面的点的坐标代表的是0,而且这个点坐标不在被检查过的列表里面,那么就把这个点的坐标位置加入到队列当中,下面同理
if position.get(down_position)=="0" and down_position not in checked_position:
m_deque.append(down_position)
if position.get(left_position)=="0" and left_position not in checked_position:
m_deque.append(left_position)
if position.get(right_position)=="0" and right_position not in checked_position:
m_deque.append(right_position)
all_line=checked_position+[end]
#这个all_line表示记录过的点,再加上出口这个点(就是说我这个程序从起点到终点它到过了什么地方,那么接下来就会通过这个列表找出迷宫的路)
#---------------------------------------------------------
#寻找出那条从起点到终点的路径
every_end=(end)
#寻找从终点开始,往前找
line=[]
#路径坐标的列表
line_dulr=[]
#路径上下左右方向的列表
while every_end!=start:
#只要找到的这个点不是起点,那么就继续找
up_xy=(every_end[0],every_end[1]-1)
down_xy=(every_end[0],every_end[1]+1)
left_xy=(every_end[0]-1,every_end[1])
right_xy=(every_end[0]+1,every_end[1])
#返回这个被找的点的上下左右的坐标信息
#注意这个下面必须要用elif!!!!!!!!!不能用都用if!!!!!!
if position.get(up_xy)=="0" and up_xy in all_line:
#如果这个点的上面点是0(表示可以走的路),而且这个点是被记录过的(表示这个点就是路径中的一个点)
index=all_line.index(up_xy)
#返回这个点在列表中的位置
all_line=all_line[:index]
#更新这个列表,就是说这个列表的最后一个元素是该点,那么下次再往前找位置的时候,眼光想起看就行了
line.append(up_xy)
#既然这个点是的话,那么就把这个点添加到最终的路径里面去
line_dulr.append("D")
#由于是反向走的,所以上面的这个坐标就要往下走
every_end = up_xy
#更新这个节点,然后从这个节点开始继续向前走
elif position.get(down_xy)=="0" and down_xy in all_line:
index=all_line.index(down_xy)
all_line=all_line[:index]
line.append(down_xy)
every_end=down_xy
line_dulr.append("U")
elif position.get(left_xy)=="0" and left_xy in all_line:
index=all_line.index(left_xy)
all_line=all_line[:index]
line.append(left_xy)
every_end=left_xy
line_dulr.append("R")
elif position.get(right_xy)=="0" and right_xy in all_line:
index=all_line.index(right_xy)
all_line=all_line[:index]
line.append(right_xy)
every_end=right_xy
line_dulr.append("L")
#print(line)
#路线的坐标
#print(line_dulr)
line_s=""
for i in line_dulr:
line_s=line_s+i
#把列表中的每个元素全都连接起来
print(line_s[::-1])
#输出答案,注意要反向一下,因为之前是倒着走的
6. 跳马
问题描述:
中国象棋半张棋盘如图1所示。马自左下角(0,0)向右上角(m,n)跳。规定只能往右跳,不准往左跳。比如图1中所示为一种跳行路线,并将路径总数打印出来。
输入格式:
只有一行:两个数n,m
输出格式:
只有一个数:总方案数total。
ways = 0
m, n = 8, 4
direction = [[2, -1], [1, -2], [1, 2], [2, 1]]
def fun(x, y):
global ways
if m == x and n == y:
ways += 1
return
for i in range(4):
new_x = x + direction[i][0]
new_y = y + direction[i][1]
if -1 < new_x < 9 and -1 < new_y < 5:
fun(new_x, new_y)
fun(0, 0)
print(ways) # 37
7. 路径之谜
小明冒充X星球的骑士,进入了一个奇怪的城堡。
城堡里边什么都没有,只有方形石头铺成的地面。
假设城堡地面是 n x n 个方格。【如图1.png】所示。
按习俗,骑士要从西北角走到东南角。
可以横向或纵向移动,但不能斜着走,也不能跳跃。
每走到一个新方格,就要向正北方和正西方各射一箭。
(城堡的西墙和北墙内各有 n 个靶子)
同一个方格只允许经过一次。但不必做完所有的方格。
如果只给出靶子上箭的数目,你能推断出骑士的行走路线吗?
有时是可以的,比如图1.png中的例子。
本题的要求就是已知箭靶数字,求骑士的行走路径(测试数据保证路径唯一)
输入:
第一行一个整数N(0<N<20),表示地面有 N x N 个方格
第二行N个整数,空格分开,表示北边的箭靶上的数字(自西向东)
第三行N个整数,空格分开,表示西边的箭靶上的数字(自北向南)
输出:
一行若干个整数,表示骑士路径。
为了方便表示,我们约定每个小格子用一个数字代表,从西北角开始编号: 0,1,2,3…
比如,图1.png中的方块编号为:
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
示例:
用户输入:
4
2 4 3 4
4 3 3 3
程序应该输出:
0 4 5 1 2 3 7 11 10 9 13 14 15
资源约定:
峰值内存消耗 < 256M
CPU消耗 < 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.7及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。
# n = int(input())
# x_ls = [int(i) for i in input().split(" ")]
# y_ls = [int(i) for i in input().split(" ")]
n = 4
x_ls = [2, 4, 3, 4]
y_ls = [4, 3, 3, 3]
map_vis = [[False for p in range(21)] for q in range(21)]
direction = [[0, -1], [0, 1], [-1, 0], [1, 0]] # 方向:上 下 左 右
path = [0 for i in range(401)] # 记录走过的点
total = sum(x_ls) + sum(y_ls)
sun = False
def check(): # 判断是否完成,如果有一个为零,就不能往下走了
for i in range(0, n):
if x_ls[i] != 0 or y_ls[i] != 0:
return False
return True
def dfs(x, y, num):
global sun
path[num] = y*n + x # 坐标
map_vis[x][y] = True
x_ls[x] -= 1
y_ls[y] -= 1
if check() and x == n-1 and y == n-1:
sun = True
return
for i in range(4):
nx = x+direction[i][0]
ny = y+direction[i][1]
if not sun and not map_vis[nx][ny] and -1 < nx < n and -1 < ny < n:
if x_ls[nx] > 0 and y_ls[ny] > 0:
dfs(nx, ny, num+1)
# 回溯
map_vis[nx][ny] = False
x_ls[nx] += 1
y_ls[ny] += 1
dfs(0, 0, 0)
print(path[:total//2]) # [0, 4, 5, 1, 2, 3, 7, 11, 10, 9, 13, 14, 15]
8. 未名湖边的烦恼
问题描述
每年冬天,北大未名湖上都是滑冰的好地方。北大体育组准备了许多冰鞋,可是人太多了,每天下午收工后,常常一双冰鞋都不剩。
每天早上,租鞋窗口都会排起长龙,假设有还鞋的m个,有需要租鞋的n个。现在的问题是,这些人有多少种排法,可以避免出现体育组没有冰鞋可租的尴尬场面。(两个同样需求的人(比如都是租鞋或都是还鞋)交换位置是同一种排法)
输入格式
两个整数,表示m和n
输出格式
一个整数,表示队伍的排法的方案数。
样例输入
3 2
样例输出
5
数据规模和约定
m,n∈[0,18]
def fun(m, n):
if m < n:
return 0
elif n == 0:
return 1
else:
return fun(m-1, n) + fun(m, n-1)
m, n = input().split(" ")
fin = fun(int(m), int(n))
print(fin)
9. 大臣的旅费
问题描述
很久以前,T王国空前繁荣。为了更好地管理国家,王国修建了大量的快速路,用于连接首都和王国内的各大城市。
为节省经费,T国的大臣们经过思考,制定了一套优秀的修建方案,使得任何一个大城市都能从首都直接或者通过其他大城市间接到达。同时,如果不重复经过大城市,从首都到达每个大城市的方案都是唯一的。
J是T国重要大臣,他巡查于各大城市之间,体察民情。所以,从一个城市马不停蹄地到另一个城市成了J最常做的事情。他有一个钱袋,用于存放往来城市间的路费。
聪明的J发现,如果不在某个城市停下来修整,在连续行进过程中,他所花的路费与他已走过的距离有关,在走第x千米到第x+1千米这一千米中(x是整数),他花费的路费是x+10这么多。也就是说走1千米花费11,走2千米要花费23。
J大臣想知道:他从某一个城市出发,中间不休息,到达另一个城市,所有可能花费的路费中最多是多少呢?
输入格式
输入的第一行包含一个整数n,表示包括首都在内的T王国的城市数
城市从1开始依次编号,1号城市为首都。
接下来n-1行,描述T国的高速路(T国的高速路一定是n-1条)
每行三个整数Pi, Qi, Di,表示城市Pi和城市Qi之间有一条高速路,长度为Di千米。
输出格式
输出一个整数,表示大臣J最多花费的路费是多少。
样例输入1
5
1 2 2
1 3 1
2 4 5
2 5 4
样例输出1
135
输出格式
大臣J从城市4到城市5要花费135的路费。
# 蒙圈了,借鉴别人的
cnt=0
node=0
def dfs(v,k): #进行dfs搜索
global cnt
global node
global vis
if k>cnt:
cnt=k
node=v
for i in range(len(E[v])):
if vis[E[v][i][0]]==False: #没访问过的点都进行一次dfs
vis[E[v][i][0]]=True #进行标记
dfs(E[v][i][0],k+E[v][i][1])
vis[E[v][i][0]]=False #回溯
n=int(input())
E=[[]for i in range(n+1)]
vis=[False for i in range(n+1)]
for i in range(n-1):
x,y,z=map(int,input().split())
E[x].append((y,z))
E[y].append((x,z)) #将各个点进行连接,用列表数组的方式进行
vis[1]=True
dfs(1,0) #找到距离1最远的点node
vis[1]=False
cnt=0
vis[node]=True
dfs(node,0) #从node出发,找到最远的点,就是所要求的最远距离
res=0
for i in range(1,cnt+1):
res+=i+10
print(res)
10. 2n皇后问题
Description
给定一个n*n的棋盘,棋盘中有一些位置不能放皇后。现在要向棋盘中放入n个黑皇后
和n个白皇后,使任意的两个黑皇后都不在同一行、同一列或同一条对角线上,任意的两
个白皇后都不在同一行、同一列或同一条对角线上。问总共有多少种放法?n小于等于8。
Input
输入的第一行为一个整数n,表示棋盘的大小。
接下来n行,每行n个0或1的整数,如果一个整数为1,表示对应的位置可以放皇后,
如果一个整数为0,表示对应的位置不可以放皇后。
Output
输出一个整数,表示总共有多少种放法。
Sample Input
No.1
4
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
No.2
4
1 0 1 1
1 1 1 1
1 1 1 1
1 1 1 1
Sample Output
No.1
2
No.2
0