四塔汉诺塔问题、TC的火柴

题目描述

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

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

输入

该题含有多组测试数据,每组一个正整数n。(0<n<=50000)

输出

一个正整数,表示把n个盘子从第1根柱子移动到第4根柱子需要的最少移动次数mod 10000的值。

样例输入

15

样例输出 

129

题目思路:

 再思考过程中,此题需要与三塔汉诺塔联系起来,熟悉三塔汉诺塔的模型不难推出n个圆盘所需移动次数为f[n] = 2 * f[n-1] + 1,且f[1] = 1。那么在四塔汉诺塔中,我们假定四塔汉诺塔n个圆盘所需移动次数为dp[n],那么我们先将j个圆盘通过四塔移动到B或者C塔上,次数为dp[j],对剩下的n-j个圆盘通过三塔移动次数放在D上,次数为f[n-j],因为n-j个圆盘皆为大圆盘,所以对接下来的圆盘移动不会造成影响,剩下j个圆盘则用四塔方法挪动至D塔上,次数为dp[j],所以n个圆盘的四塔汉诺塔所需移动次数为f[n-j] + 2*dp[j]。然后用暴搜法查找到最佳的j为多少。

f = [0 for i in range(1005)]
dp = [100000 for i in range(1005)]
while(True):
    n = int(input())
    for i in range(1,n+1):
        f[i] = 2*f[i-1] + 1
    dp[1] = 1
    for i in range(n+1):
        for j in range(1,i):
            dp[i] = min(dp[i],(f[i-j]+2 * dp[j]))
    print(dp[n])

但是:

 想要通过这种方法在OJ上完成这道题是不可行的,python容易内存撑爆导致运行错误,建议先用上方方法测试多组样例数据,找出规律,优化代码。下方为复杂度为O(n)的该题算法:

while(True):
    n = int(input())
    temp, f, cnt, ans = 0,1,1,2
    for i in range(1, n+1):
        temp = (temp + f) % 10000
        if cnt == i: 
            cnt += ans
            ans += 1
            f = (f*2) %10000
    print(temp)

题目描述

今天,TC买了一盒火柴,打算和小yh比拼谁能用有限的火柴得到一个最大数字。火柴拼数字规则是,拼出零到九分别需要6、2、5、5、4、5、6、3、7、6个火柴。 
现在给TC a个不同火柴数,求你帮TC计算不同的火柴数a分别能组成的最大数字,如果不能组成数字,输出-1。 

输入

第一行输入一个n。 
接下来n行,每行一个数a(0<=a<=103) 

输出

每行输出一个能组成的最大数字。

样例输入 

3
1
2
4

样例输出

-1
1
11

提示 

TC说火柴要省着用

题目解析:

        贪心算法,要组成最大数字,当然是位数越多越大,所需火柴最小的数字是1,其次是7,其余消耗火柴太大,所以只需判断火柴数是否是2的倍数,如果是则全部组成1,如果不是则把剩余一根和第一个1组成替换成7,其余全部组成1

def judge():
    ans = int(a/2)
    if ans == 0:
        print(-1)
    else:
        if a%2 == 0:
            print(1,end = '')
        else:
            print(7,end = '')
        for i in range(int(ans)-1):
            print(1,end = '')
        print()
while(True):
    n = int(input())
    for i in range(n):
        a = int(input())
        judge()
    break

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值