HNUCM-2022年秋季学期《算法分析与设计》练习3

 python版本答案

目录

问题 A: 超级青蛙 

问题 B: 汉诺塔 

 问题 C: 汉诺塔II

问题 D: Kimi的早餐店

问题 E: 字母全排列

问题 F: 九数组分数

问题 G: 汉诺塔III

 问题 H: 高桥和低桥


问题 A: 超级青蛙 

题目描述:

一只超级青蛙一次可以跳上1级台阶,也可以跳上2级……它也能够跳上n级台阶。请问,该青蛙跳上一个n级的台阶总共有多少种跳法?

递归:

def jump(x: int):
    if x <= 2:
        return x
    else:
        return 2 * jump(x - 1)


while True:
    try:
        n = int(input())
        print(jump(n))
    except:
        break

 非递归:

nums = [1, 2, 4]
while True:
    try:
        n = int(input())
        if len(nums) < n:
            for _ in range(len(nums), n):
                nums.append(nums[-1] * 2)
        print(nums[n - 1])
    except:
        break

问题 B: 汉诺塔 

题目描述:

使用递归编写一个程序实现汉诺塔问题,要求在输入圆盘数量之后,输出圆盘的移动步骤,输出格式示例如下:

第1步:1号盘从A柱移至B柱
第2步:2号盘从A柱移至C柱

递归:

step = 0  # 步数记录标签
cnt = 0  # 测试组数记录标签


def move(x: int, f: str, t: str):
    global step
    step += 1
    print(f"第{step}步:{x}号盘从{f}柱移至{t}柱")


def hn(x: int, a: str, b: str, c: str):
    if x > 0:
        hn(x - 1, a, c, b)
        move(x, a, c)
        hn(x - 1, b, a, c)


while True:
    try:
        n = int(input())
        step = 0
        if cnt != 0:
            print()  # 不是第一组就输出一个空白的间隔行
        cnt += 1
        hn(n, 'A', 'B', 'C')
    except:
        break

 问题 C: 汉诺塔II

题目描述:

用1,2,...,n表示n个盘子,称为1号盘,2号盘,...。号数大盘子就大。经典的汉诺塔问题经常作为一个递归的经典例题存在。可能有人并不知道汉诺塔问题的典故。汉诺塔来源于印度传说的一个故事,上帝创造世界时作了三根金刚石柱子,在一根柱子上从下往上按大小顺序摞着64片黄金圆盘。上帝命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一回只能移动一个圆盘。我们知道最少需要移动2^64-1次.在移动过程中发现,有的圆盘移动次数多,有的少 。 告之盘子总数和盘号,计算该盘子的移动次数.

非递归: 

t = int(input())
while t > 0:
    t -= 1
    n, k = map(int, input().split())
    print(2 ** (n - k))  # 不难发现输出次数为2的n-k次方

问题 D: Kimi的早餐店

题目描述:

Kimi开了一家早餐店,这家店的客人都有个奇怪的癖好:他们只要来这家店吃过一次早餐,就会每天都过来;并且,所有人在这家店吃了两天早餐后,接下来每天都会带一位新朋友一起来品尝。
于是,这家店的客人从最初一个人发展成浩浩荡荡成百上千人:1、1、2、3、5……
现在,Kimi想请你帮忙统计一下,某一段时间范围那他总共卖出多少份早餐(假设每位客人只吃一份早餐)。

非递归:

foods = [1, 1, 2, 3]
for _ in range(4, 80):
    foods.append(foods[-1] + foods[-2])
# print(len(foods))
while True:
    try:
        f, t = map(int, input().split())
        # print(foods[f - 1:t])
        print(sum(foods[f - 1:t]))
    except:
        break

问题 E: 字母全排列

题目描述:

编写一个程序,使用递归算法输出一个一维字符数组中所有字符的全排列,假设字符都不一样。例如{'a','b','c'}的全排列为(a,b,c), (a,c,b), (b,a,c), (b,c,a), (c,a,b), (c,b,a)

递归:

chars = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
         'w', 'x', 'y', 'z']
res = []  # 排列存储列表
cnt = 0


def fun(lis: list):
    if not lis:
        print("".join(res))  # 如果待排列的数组为空,就说明以排列完,数据排列结果
    else:
        l = len(lis)
        for i in range(l):
            res.append(lis[i])
            fun(lis[:l]) if i == l else fun(lis[:i] + lis[i + 1:])
            del res[-1]


while True:
    try:
        n = int(input())
        if cnt != 0:
            print()
        cnt += 1
        fun(chars[:n])
    except:
        break

问题 F: 九数组分数

题目描述:

1, 2, 3...9 这九个数字组成一个分数,其值恰好为1/3,要求每个数字出现且只能出现一次,如何组合?编写程序输出所有的组合。

偷鸡:

print("5823/17469 5832/17496")

递归:

nums = ['1', '2', '3', '4', '5', '6', '7', '8', '9']
res = []  # 排列存储列表
cnt = 0


def fun(lis: list):
    global cnt
    if not lis:
        # print("".join(res))  # 如果待排列的数组为空,就说明以排列完,数据排列结果
        x = "".join(res[:4])
        y = "".join(res[4:])
        if int(x) / int(y) == 1 / 3:
            print(f"{x}/{y}", end='') if cnt == 0 else print(f" {x}/{y}", end='')
            cnt += 1
    else:
        length = len(lis)
        # print(f"length={length}")
        for i in range(length):
            res.append(lis[i])
            fun(lis[:i]) if i == length else fun(lis[:i] + lis[i + 1:])
            del res[-1]


try:
    fun(nums)
    print()
except:
    pass

问题 G: 汉诺塔III

题目描述:

“汉诺塔”是一个众所周知的古老游戏。
现在我们把问题稍微改变一下:如果一共有4根柱子,而不是3根,那么至少需要移动盘子多少次,才能把所有的盘子从第1根柱子移动到第4根柱子上呢?


为了编程方便,您只需要输出这个结果mod 10000的值。

python较慢,递归容易超时。

非递归:

while True:
    try:
        n = int(input())
        temp, k, cnt, ctl = 0, 1, 1, 2
        for i in range(1, n + 1):
            temp = (temp + k) % 10000
            if cnt == i:
                cnt, ctl, k = cnt + ctl, ctl + 1, (k * 2) % 10000
        print(temp)
    except:
        break

 问题 H: 高桥和低桥

题目描述:

有个脑筋急转弯是这样的:有距离很近的一高一低两座桥,两次洪水之后高桥被淹了两次,低桥却只被淹了一次,为什么?答案是:因为低桥太低了,第一次洪水退去之后水位依然在低桥之上,所以不算“淹了两次”。举例说明:
假定高桥和低桥的高度分别是5和2,初始水位为1
第一次洪水:水位提高到6(两个桥都被淹),退到2(高桥不再被淹,但低桥仍然被淹)
第二次洪水:水位提高到8(高桥又被淹了),退到3。
没错,文字游戏。关键在于“又”的含义。如果某次洪水退去之后一座桥仍然被淹,那么下次洪水来临水位提高时不能算“又”淹一次。
输入n座桥的高度以及第i次洪水的涨水水位ai和退水水位bi,统计有多少座桥至少被淹了k次。初始水位为1,且每次洪水的涨水水位一定大于上次洪水的退水水位。

(数据量太大,爆内存了,还在思考。)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值