Python-递归与动态规划

题目一:

给定数组arr, arr中所有的值都为正数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个整数aim代表要找的钱数,求组成aim的最少货币数。

例arr=[5,2,10,1], aim=5

思路:

1、定义一个len(arr)行aim+1列矩阵,默认值为最大值。

2、初始化,第一列为0,第一行如下每一位代表,aim=0,1,2,3,4,5,一直到5,只需要一张5元。

0  max max max max 1

0

0

0

3、dp[i][j] = min{dp[i-1][j], dp[i][j-arr[i]+1]} 

dp[i-1][j]代表直接使用不使用本行面值,dp[i][j-arr[i]]+1代表使用本行

def findmoney(arr,aim):
    max=float('inf')
    l = [[max for i in range(aim+1)] for i in range(len(arr))]
    for i in range(len(arr)):
        l[i][0]=0
    for i in range(1,aim//arr[0]+1):
        l[0][i*arr[0]]=i
    for i in range(1,len(arr)):
        for j in range(1,aim+1):
            left=max
            if j-arr[i]>=0:
                left=l[i][j-arr[i]]+1
            l[i][j]=min(l[i-1][j],left)
    print(l)
findmoney([5,2,10,1],20)

题一补充:

给定数组arr, arr中所有的值都为正数且不重复。每个值代表一张钱的面值,每种面值的货币可以使用一张,再给定一个整数aim代表要找的钱数,求组成aim的最少货币数。

1、同上一题第一步。

2、第一列同上一题,第一行只将arr[0]位置置1.

3、dp[i][j]=min(dp[i-1][j],dp[i-1][j-arr[i]])

dp[i-1][j]代表不使用本行货币

dp[i-1][j-arr[i]]代表使用本行货币

def findmoney(arr,aim):
    max=float('inf')
    l = [[max for i in range(aim+1)] for i in range(len(arr))]
    for i in range(len(arr)):
        l[i][0]=0
    l[0][arr[0]]=1
    for i in range(1,len(arr)):
        for j in range(1,aim+1):
            left=max
            if j-arr[i]>=0:
                left=l[i-1][j-arr[i]]+1
            l[i][j]=min(l[i-1][j],left)
    print(l)
    print(l[i][j])
findmoney([5,2,10,1],15)

题目二:

给定数组arr, arr中所有的值都为正数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个整数aim代表要找的钱数,求换钱有多少种方法。

例arr=[5,2,10,1], aim=5

思路:

1、定义一个len(arr)行aim+1列矩阵,默认值为0。

2、初始化,第一列为1,代表每个面值都不用,有一种方案,第一行如下每一位代表,aim=0,1,2,3,4,5,一直到5,只需要一张5元。

1  0 0 0 0 1

1  0 1 0 1 0

1

1

3、num=dp[i-1][j-arr[i]*k] for k in range(aim+1); dp[i][j] = num

dp[i-1][j]代表直接使用不使用本行面值,dp[i][j-arr[i]]+1代表使用本行

def findmoney(arr,aim):
    # max=float('inf')
    # max=float('inf')
    # num=0
    l = [[0 for i in range(aim+1)] for i in range(len(arr))]
    for i in range(len(arr)):
        l[i][0]=1
    for i in range(1,aim//arr[0]+1):
        l[0][i*arr[0]]=1
    for i in range(1,len(arr)):
        for j in range(1,aim+1):
            num=0
            for k in range(aim+1):
                if j-arr[i]*k>=0:
                    num+=l[i-1][j-k*arr[i]]
            l[i][j]=num
    print(l)
    print(l[i][j])
findmoney([5,2,10,1],10)

优化步骤三:

dp[i][j] = dp[i-1][j]+dp[i][j-arr[i]]

def findmoney(arr,aim):
    # max=float('inf')
    # max=float('inf')
    # num=0
    l = [[0 for i in range(aim+1)] for i in range(len(arr))]
    for i in range(len(arr)):
        l[i][0]=1
    for i in range(1,aim//arr[0]+1):
        l[0][i*arr[0]]=1
    for i in range(1,len(arr)):
        for j in range(1,aim+1):
            l[i][j]=l[i-1][j]
            if j-arr[i]>=0:
                    l[i][j]+=l[i][j-arr[i]]
    print(l)
    print(l[i][j])
findmoney([5,2,10,1],10)

题目三:

给定k个整数+的序列{N1,N2,...,Nk },其任意连续子序列可表示为{ Ni, Ni+1, ..., Nj },其中 1 <= i <= j <= k。最大连续子序列是所有连续子序中元素和最大的一个,例如给定序列{ -2, 11, -4, 13, -5, -2 },其最大连续子序列为{11,-4,13},最大连续子序列和即为20。

def findmax(arr):
    n=len(arr)
    l=[0 for i in range(n)]
    l[0]=arr[0]
    for i in range(1,n):
        l[i]=max(arr[i]+l[i-1],arr[i])
    print(max(l))
findmax([-2,11,-4,13,-5,-2,14])

题三扩展:

输出乘积最大序列。

def find(arr):
    n=len(arr)
    l=[0 for i in range(n)]
    g=[0 for i in range(n)]
    l[0]=arr[0]
    g[0]=arr[0]
    for i in range(1,n):
        l[i]=max(l[i-1]*arr[i],arr[i],g[i-1]*arr[i])
        g[i]=min(l[i-1]*arr[i],arr[i],g[i-1]*arr[i])
    print(l[-1])
find([-2, 11, -4, 13, -5, -2])

题目四:

亚历克斯和李用几堆石子在做游戏。偶数堆石子排成一行,每堆都有正整数颗石子 piles[i] 。

游戏以谁手中的石子最多来决出胜负。石子的总数是奇数,所以没有平局。

亚历克斯和李轮流进行,亚历克斯先开始。 每回合,玩家从行的开始或结束处取走整堆石头。 这种情况一直持续到没有更多的石子堆为止,此时手中石子最多的玩家获胜。

假设亚历克斯和李都发挥出最佳水平,当亚历克斯赢得比赛时返回 true ,当李赢得比赛时返回 false 。

示例:

输入:[5,3,4,5]
输出:true
解释:
亚历克斯先开始,只能拿前 5 颗或后 5 颗石子 。
假设他取了前 5 颗,这一行就变成了 [3,4,5] 。
如果李拿走前 3 颗,那么剩下的是 [4,5],亚历克斯拿走后 5 颗赢得 10 分。
如果李拿走后 5 颗,那么剩下的是 [3,4],亚历克斯拿走后 4 颗赢得 9 分。
这表明,取前 5 颗石子对亚历克斯来说是一个胜利的举动,所以我们返回 true 。
def stoneGame(piles):
    n = len(piles)
    dp = piles[:]

    for d in range(1, n):
        for i in range(n - d):
            dp[i] = max(piles[i] - dp[i + 1], piles[i + d] - dp[i])
    # print(dp)
    print(dp[0])
stoneGame([5,3,4,5])

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值