【思特奇杯·云上蓝桥-算法集训营】第2周

蓝桥杯训练营第二周作业

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值