动态规划

动态规划,就是找问题子问题,并且建立关系,如何找出有用的子问题,很关键

1、1,3,5面值硬币,求n元,至少需要几枚硬币组合,比如100元,

  • 如果当前1元,99元至少需要多少

  • 如果当前3元,97元至少需要多少

  • 如果当前5元,95元至少需要多少
    只要求出三种情况,最小即为所求,递推关系

      d[i] = min(d[i-1]+1, d[i-3]+1, d[i-5]+1), i >= 5
    
def get_coin(coins, n):
    # 假设i元需要j枚硬币d[i]=j,d[0]=0,d[1]=1
    # d[i]=min{d[i-1]+1,d[i-3]+1,d[i-5]+1}
    # coins 是正整数数组,n也为正整数
    coins.sort()
    c_max = coins[-1]
    c_min = coins[0]
    d = [0]*(max(n, c_max)+1)
    
    # 如果n在coins d[n] = 1
    if n in coins:
        return 1
    # 对d赋初值
    for el in coins:
        d[el] = 1
    # 递推求d[n]
    # 从1开始到n
 
    
    for N in range(1, n+1):
        # 如果,则需要计算d[N]
        if d[N] == 0:
            # N 可以写成比N-{coins},最小的
            d[N] = amount
            for coin in coins:
                if N > coin:
                    if d[N-coin] !=0:
                        d[N] = min(d[N], 1+d[N-coin])
                else:
                    break
    return d[n]
coins = [186,419,83,408]
n = 6489
print get_coin(coins, n)

2、最大非降子序列长度

  • 以a(j)为结尾的非降子序列长度为d[j]
  • 这样序列中以每个元素结尾的长度d[j],j = 0,1,2,...
  • d[j+1] = max{ d[i]+1,if a[j+1]>=a[i],i <j+1}
  • max{d}就是最大非降子序列的长度
def longestchildes(A):
    # d[i]表示前i+1 个元素以A[i]结尾的最大非降子序列长度
    # d[1]=1
    # 如果A[2]>=A[1], d[2]=d[1]+1,否则d[2]=1
    # if A[3]>=A[2],A[3]>=A[1],d[2]=max{d[1]+1,d[2]+1}
    # A[i]与前面进行比较,求的最大值
    d = [1]*len(numbers)
    n = len(numbers)
    for i in range(n):
        for j in range(i):
            if A[i] >= A[j]:
                d[i]=max(d[i],d[j]+1)
    print d
numbers = [2,1,3,4,3.5,3.6]
longestchildes(numbers)

3、ZigZag
求数列正负相隔最大子序列,如果1,7, 4, 9, 2, 5,1>7<4>9<2>5
本身就满足,这个和上题类似,也是以numbers[i]结尾的正负相隔最大子序列为dp[i][],这里要记录当前节点是正,还是负,这样后一个节点才好与之比较

def nepo(numbers):
    lens = len(numbers)
    dp = [[1,1] for i in range(lens)]
    dp[0] = [1,1]
    i = 0

    while i < lens:
        j = 0
        while j < i:
            if numbers[i] > numbers[j]:
                dp[i][0] = max(dp[i][0], dp[j][1]+1)
            if numbers[i] < numbers[j]:
                dp[i][1] = max(dp[i][1], dp[j][0]+1)
            j += 1
        i += 1
    return dp

4、 BadNeighbors
求不相邻子序列最大和,首尾算是相邻的两个数
这个题要注意dp[i][]表示donations[i]最大不相邻子序列最大和,包含首个数,和不包含首个数最大和,

def badNeighbors(donations):
    lens = len(donations)
    dp = [0]*lens
    i = 0
    if lens == 0:
        return 0
    if lens == 1:
        return donations[0]
    if lens == 2 or lens == 3:
        return max(donations)

    dp = [[0 for i in range(2)] for i in range(lens)]
    dp[0] = [donations[0],0]
    dp[1] = [0,donations[1]]
    i = 2
    while i < lens:
        j = 0
        while j < i-1:
            dp[i][0] = max(dp[j][0]+donations[i], dp[i][0])
            dp[i][1] = max(dp[j][1]+donations[i], dp[i][1])
            j += 1
        i += 1
    return dp

5、平面上有N*M 个格子,每个格子中放着一定数量的苹果。你送左上角的格子开始,每一步只能向下或是向右走,每次走到一个格子上就把格子里的苹果收集起来,这样下去,你最多能收集到多少个苹果。
看一个简单例子,左边是原来图,右面是向下或向右两种行动方式能获得最大苹果数,换一种说法每一个格子只能从左面或上面获得苹果,要使本格子苹果最多,只能选择Max{左,上}的苹果

import numpy as np
# 递归
def get_most_apples_by_recursion(apples, M, N):
    # M 行,N列
    if M == 0 and N == 0:
        return apples[0][0]
    if N == 0:
        return get_most_apples_by_recursion(apple,M-1, N) + apples[M][N]
    if M == 0:
        return get_most_apples_by_recursion(apples, M, N-1)+apples[M][N]
    return max(get_most_apples_by_recursion(apples, M, N-1), get_most_apples_by_recursion(apples, M-1, N))+apples[M][N]
# 迭代
def get_most_apples_by_iteration(apples, M, N):
    # j 行 i 列
    for i in range(N):
        for j in range(M):
            if j > 0 and i > 0:
                apples[j][i] += max(apples[j-1][i], apples[j][i-1])
            elif j > 0 and i == 0:
                apples[j][i] += apples[j-1][i]
            elif i > 0 and j == 0:
                apples[j][i] += apples[j][i-1]
apple = [[5,2,4,6], [3,7,8,2], [9,3,5,7], [1,4,3,8]]

# M 行, N列
M = len(apple)
N = len(apple[0])
A = [[0 for i in range(N)] for i in range(M)]
get_most_apples_by_iteration(apple, M, N)
print apple
  1. Can I Win给定一堆数比如1到max,目标数desir,甲乙两人从堆中任意抽取数字(不能放回),当甲乙抽出数字总和大于等于desir,则最后一方获胜,现在问给出max与desir,判断甲能不能获胜。如果总和小于desir甲乙都不能获胜。
    第一步:一堆数中最大的数大于等于desir,则甲选取该数,甲获胜,否则甲选取数A,desir = desir-A
    第二步:如果最大数大于desir,乙获胜,否则,乙选取数B,desir = desir-B
    问题可以总结为 question(numbers,desir),每一步都可以化为这样的问题,desir在不断变小
def question(nums,desir):
  
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容