数据结构与算法Python版第五周OJ作业

1 进制转换(10分)

题目内容:

给定一个M进制的数,请将其转换为N进制并输出

输入格式:

两行,第一行为空格分隔的两个数字,分别为10进制表示的M与N;其中M, N均满足2 ≤ M、N ≤ 36

第二行为待转换的数字,其中每位超过9的部分从10至36分别用大写字母A-Z表示;输入数据保证其中最大位数对应数字不超过M

输出格式:

一行字符串,表示转换后的N进制数

输入样例:

8 16

‭473‬

输出样例:

‭13B‬

解题思路:

先把待转换的数字转换成十进制,之后再利用递归算法从十进制转换成目标进制,此外还考虑了负数和有小数的情况,负数最后输出时要在前面多打印一个负号,有小数的情况得拆分成整数部分和小数部分分别处理。
用例1显示程序异常是测评机的问题,不会算入评分。
在这里插入图片描述

程序代码:

def tostr(s, n): # 十进制转其他进制
    convertString = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    if s < n:
        return convertString[s]
    else:
        return tostr(s // n, n) + convertString[s % n]


def ftostr(s, n): # 小数十进制转其他进制
    convertString = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    if s == 0:
        return ''
    else:
        return convertString[int(s * n)] + ftostr((s * n) % 1, n)


def toten(s, m): # 其他进制转十进制
    convertString = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    n = 0
    sum = 0
    for i in s[::-1]:
        if i in convertString:
            i = convertString.index(i)
            sum += i * (m ** n)
            n += 1
    return sum


def ftoten(s, m): # 小数其他进制转十进制
    convertString = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    n = -1
    sum = 0
    for i in s:
        i = convertString.index(i)
        sum += i * (m ** n)
        n -= 1
    return sum


m, n = map(int, input().split())
S = input()
if '.' in S: # 判断是否带小数
    S, B = S.split('.')
    s = toten(S, m)
    b = ftoten(B, m)
    if S[0] == '-': # 判断是否为负数
        print('-' + tostr(s, n) + '.' + ftostr(b, n))
    else:
        print(tostr(s, n) + '.' + ftostr(b, n))
else:
    s = toten(S, m)
    if S[0] == '-':
        print('-' + tostr(s, n))
    else:
        print(tostr(s, n))

2 四柱汉诺塔(10分)

题目内容:

如课上所说,汉诺塔问题源于印度一个古老传说。对于原始的汉诺塔游戏,可供玩家操作的空间一共只有三根柱子,导致按原传说的要求,需要超过1.8*10^19步才能解开。

透过新增柱子可以大幅度地减少需要的步数。此处要求在给出指定的盘数,柱子数量为4(即限制为4根柱子)且不改变原有传说的其他规则的限制下,找出完成迁移的最小步骤数。

输入格式:

一个非负整数M,M代表盘数,M<=1000。

输出格式:

一个非负整数,表示完成迁移的最小步骤数。

输入样例:

3

输出样例:

5

解题思路1:

利用递归算法,先将上面N-2个盘片从A柱移动到B柱,然后将第N-1个盘片从A柱移动到C柱,接着将第N个盘片从A柱移动到D柱,再把第N-1个盘片从C柱移动到D柱,最后将上面N-2个盘片从B柱移动到D柱,基本结束条件是移动1个盘片,用一个全局变量n来统计移动盘片的次数。

程序代码1:

def moveTower(height, a, b, c, d):
    if height >= 2:
        moveTower(height - 2, a, c, d, b)
        moveDisk(height - 1, a, c)
        moveDisk(height, a, d)
        moveDisk(height - 1, c, d)
        moveTower(height - 2, b, a, c, d)
    elif height == 1:
        moveDisk(height, a, d)


def moveDisk(disk, a, d):
    global n
    n += 1 # 每次移动盘片时,n加1
    # print('Moving disk[{}] from {} to {}'.format(disk, a, d))


n = 0 # 全局变量n,用于统计盘片移动的次数
height = int(input())
moveTower(height, '#1', '#2', '#3', '#4')
print(n)

解题思路2:

由于递归算法的运行时间超出题目的限制,所以我们不妨换个思路。首先我们回顾一下三柱汉诺塔,对于三柱汉诺塔问题,他的移动次数是固定的,若有n个盘片,那么移动次数就是2^n - 1。
设F[n]为n个盘片所需移动的最小次数,四柱汉诺塔的移动次序可分为三步:

  1. 先将上面k个盘片从a柱经过c、d柱移动到b柱,移动次数为F[k]
  2. 接着将下面n-k个盘片从a柱经过c柱移动到d柱,这是一个三柱汉诺塔问题,移动次数为2^(n-k) - 1
  3. 最后将k个盘片从b柱经过a、c柱移动到d柱,移动次数为F[k]

所以n个盘片所需移动的总次数为2 * F[k] + 2^(n-k) - 1。因为题目要求的是移动的最小次数,所以F[n] = min(2 * F[k] + 2^(n-k) - 1),k=1,2,…,n-1
初值:当n = 0时,F[0] = 0;当n = 1时,F[1] = 1;当n = 2时,F[2] = 3

程序代码2:

F = [0, 1, 3]
temp = float('inf')
n = int(input())
if n < 3:
    print(F[n])
else:
    for i in range(3, n+1):
        F.append(temp)
        for k in range(1, i):
            if (2 * F[k] + 2 ** (i - k) - 1) < F[i]:
                F[i] = 2 * F[k] + 2 ** (i - k) - 1
    print(F[n])

3 ASCII谢尔宾斯基地毯(10分)

题目内容:
在这里插入图片描述
谢尔宾斯基地毯是形如上图的正方形分形图案,每个地毯可分为等大小的9份,其中中央挖空,其余均由更小的地毯组成。

现给定地毯大小(行数)与组成地毯的字符元素,请打印相应的地毯图形。

注:空腔以半角空格表示;当给定字符元素长度不为1时空格数须与字符长度对应

输入格式:

输入为两行,分别为地毯大小正整数N与组成元素字符串c

输入数据保证N为3的正整数幂

输出格式:

由N行长度为N*len©的字符串构成的谢尔宾斯基地毯

输入样例:

9

[]

输出样例:

[][][][][][][][][]
[]  [][]  [][]  []
[][][][][][][][][]
[][][]      [][][]
[]  []      []  []
[][][]      [][][]
[][][][][][][][][]
[]  [][]  [][]  []
[][][][][][][][][]

解题思路:

一个谢尔宾斯基地毯可以看成将一个实心正方形把中间挖空再构造四周八个小的谢尔宾斯基地毯,所以我们可以先按照边长和组成元素字符串构造一个实心的正方形,接着将中间用空格填充,再递归构造四周八个小谢尔宾斯基地毯,当边长小于3无法继续分解时结束递归并打印整个图案。

程序代码:

def carpet(N, L, x, y): # x,y为左上角元素在列表中的索引
    if N >= 3:
        draw(N, L, x, y)
        carpet(N // 3, L, x, y)
        carpet(N // 3, L, x + N // 3, y)
        carpet(N // 3, L, x + 2 * N // 3, y)
        carpet(N // 3, L, x, y + N // 3)
        carpet(N // 3, L, x + 2 * N // 3, y + N // 3)
        carpet(N // 3, L, x, y + 2 * N // 3)
        carpet(N // 3, L, x + N // 3, y + 2 * N // 3)
        carpet(N // 3, L, x + 2 * N // 3, y + 2 * N // 3)


def draw(N, L, x, y):
    for i in range(x + N // 3, x + 2 * N // 3):
        for j in range(y + N // 3, y + 2 * N // 3):
            square[i][j] = ' ' * L


n = int(input())
c = input()
square = [[c for i in range(n)] for i in range(n)] # 生成实心的正方形
l = len(c) # 所给字符串的长度等于挖空中间时所要填充的空格个数
carpet(n, l, 0, 0)
for i in range(n):
    for j in range(n):
        print(square[i][j], end='')
    print()
发布了9 篇原创文章 · 获赞 0 · 访问量 1079

猜你喜欢

转载自blog.csdn.net/Divine0/article/details/105028894
今日推荐