MOOC数算OJ-2

在这里插入图片描述代码

def transition(M,N,strnum):
    numList=['0','1','2','3','4','5','6','7','8','9','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']
    #把M进制的num转化为10进制
    numlength=len(strnum)
    Ten_num=0
    for i in range(1,numlength+1):
        Ten_num=Ten_num+numList.index(strnum[-i])*(M**(i-1))
    
    #把10进制的num转化为N进制
    N_num=''
    while Ten_num!=0:
        N_num=numList[Ten_num%N]+N_num
        Ten_num=Ten_num//N
    return N_num

M,N=map(int,input().split())
strnum=input()
print(transition(M,N,strnum))

代码中需要注意的地方

M,N=map(int,input().split())用来输入一行中含有多个整数
strnum[-i]由于输入的原数字是字符串形式,并且数字的最低位在字符串的末尾,因而可以使用负数的索引方式
numList的索引正好对应字符的十进制数,因而采用index索引得到字符对应的十进制数
numList.index(strnum[-i])由于输入的strnum是字符串形式,因而numList中的0-9不要写作整数类型
numList[Ten_num%N]对字符串索引取值要用中括号
N_num=numList[Ten_num%N]+N_num加法前后顺序不可以变化,保证除k取余法中对余数取得顺序

在这里插入图片描述代码

num=int(input())
memory=[0 for i in range(num+1)]#记忆

def dp(n):#n是盘子总数
    #结束条件
    if n==0:
        memory[0]=0
        return 0
    elif n==1:
        memory[1]=1
        return 1
    elif n==2:
        memory[2]=3
        return 3
    #其他情况
    else:
        if memory[n]!=0:
            return memory[n]
        else:
            step=[]
            for k in range(1,n):
                step.append(2*dp(k)+2**(n-k)-1)
            memory[n]=min(step)
            return min(step)            
print(dp(num))

详解
假设四根柱子命名分别为a b c d,需要把盘子从a柱移动到d柱:
函数dp(n)代表把n个盘子进行移动所需要的最少步骤

1、我们设将a柱最上边的k个圆盘(1<=k<n)借助b、d两个柱子移动到c上需要dp[ k ] 步
2、然后我们再把a柱上剩下的n-k个盘借助b柱移动到d柱上(不能借助c, c上的都小),那么这一步骤和三柱汉诺塔是一样的,是 2^(n-k)-1步
3、最后我们再把c上的k个圆盘借助a、b移动到d上,同样需要F[ k ]步
4、但是,要得到最小值,需要把k遍历一遍在这里插入图片描述

代码中要注意的几点

  1. 输入的盘子总数是非负整数,因而要在代码中考虑 n=0的情况
  2. 为减少递归层数,可以采用函数值缓存的方法,本代码中使用了memory列表缓存
  3. k的取值范围如果k取0,则只用到了三根柱子,一定不会是最优解;如果k取n,则先把所有盘子从a移到c,再从c移到d,显然不是最优解。同时,如果k取n的话,在递归调用的过程中会出现自己调用自己的状况,陷入了死循环。(禁止套娃!!)
    在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值