华为机试(python):动态规划

HJ16 购物单

王强决定把年终奖用于购物,他把想买的物品分为两类:主件与附件,附件是从属于某个主件的,下表就是一些主件与附件的例子:

主件 附件
电脑 打印机,扫描仪
书柜 图书
书桌 台灯,文具
工作椅

如果要买归类为附件的物品,必须先买该附件所属的主件,且每件物品只能购买一次。

每个主件可以有 0 个、 1 个或 2 个附件。附件不再有从属于自己的附件。

王强查到了每件物品的价格(都是 10 元的整数倍),而他只有 N 元的预算。除此之外,他给每件物品规定了一个重要度,用整数 1 5 表示。他希望在花费不超过 N 元的前提下,使自己的满意度达到最大。

满意度是指所购买的每件物品的价格与重要度的乘积的总和,假设设第ii件物品的价格为v[i]v[i],重要度为w[i]w[i],共选中了kk件物品,编号依次为j_1,j_2,...,j_kj1​,j2​,...,jk​,则满意度为:v[j_1]*w[j_1]+v[j_2]*w[j_2]+ … +v[j_k]*w[j_k]v[j1​]∗w[j1​]+v[j2​]∗w[j2​]+…+v[jk​]∗w[jk​]。(其中 * 为乘号)

请你帮助王强计算可获得的最大的满意度。

输入描述:

输入的第 1 行,为两个正整数N,m,用一个空格隔开:

(其中 N ( N<32000 )表示总钱数, m (m <60 )为可购买的物品的个数。)

从第 2 行到第 m+1 行,第 j 行给出了编号为 j-1 的物品的基本数据,每行有 3 个非负整数 v p q

(其中 v 表示该物品的价格( v<10000 ), p 表示该物品的重要度( 1 5 ), q 表示该物品是主件还是附件。如果 q=0 ,表示该物品为主件,如果 q>0 ,表示该物品为附件, q 是所属主件的编号)

输出描述:

 输出一个正整数,为张强可以获得的最大的满意度。

while True:
    try:
        n,m = map(int,input().split(' '))
        primary,annex = {},{}#前者为主件字典,后者为附件字典
        for i in range(1,m+1):
            x,y,z = map(int,input().split(' '))
            if z == 0:#主件
                primary[i] = [x,y]#给主件标号
            else:#附件
                if z in annex:#第二个附件
                    annex[z].append([x,y])#以主件标号为key,用append排在第一个附件之后
                else:#第一个附件
                    annex[z] = [[x,y]]
        m = len(primary)#将主件个数转化为物品个数
        dp = [[0]*(n+1) for _ in range(m+1)]
        #dp = [0]*(n+1)
        w,v = [[]],[[]]
        for key in primary:
            w_temp,v_temp = [],[]
            w_temp.append(primary[key][0])#主件的价钱
            v_temp.append(primary[key][0]*primary[key][1])#主件的满意度
            if key in annex:#若存在主件
                w_temp.append(w_temp[0]+annex[key][0][0])#主件+附件1的价钱
                v_temp.append(v_temp[0]+annex[key][0][0]*annex[key][0][1])#主件+附件1的满意度
                if len(annex[key])>1:#若存在两个附件
                    w_temp.append(w_temp[0]+annex[key][1][0])#主件+附件2的价钱
                    v_temp.append(v_temp[0]+annex[key][1][0]*annex[key][1][1])#主件+附件2的满意度
                    w_temp.append(w_temp[0]+annex[key][0][0]+annex[key][1][0])#主件+两个附件的价钱
                    v_temp.append(v_temp[0]+annex[key][0][0]*annex[key][0][1]+annex[key][1][0]*annex[key][1][1])#主件+两个附件的满意度
            w.append(w_temp)#w_temp存储这一个主件价钱的四种情况
            v.append(v_temp)#v_temp存储这一个主件满意度的四种情况
        for i in range(1,m+1):
            for j in range(10,n+1,10):#物品的价格是10的整数倍
                max_i = dp[i-1][j]
                for k in range(len(w[i])):
                    if j-w[i][k]>=0:
                        max_i = max(max_i,dp[i-1][j-w[i][k]]+v[i][k])#状态转移方程
                dp[i][j] = max_i
        print(dp[m][n])
                
        
        
                    
                
                    
        
        
    except:
        break
        

HJ24 合唱队

N 位同学站成一排,音乐老师要请最少的同学出列,使得剩下的 K 位同学排成合唱队形。

设KK位同学从左到右依次编号为 1,2…,K ,他们的身高分别为T_1,T_2,…,T_KT1​,T2​,…,TK​ ,若存在i(1\leq i\leq K)i(1≤i≤K) 使得T_1T_{i+1}>......>T_KTi​>Ti+1​>......>TK​,则称这KK名同学排成了合唱队形。

通俗来说,能找到一个同学,他的两边的同学身高都依次严格降低的队形就是合唱队形。

例子: 

123 124 125 123 121 是一个合唱队形

123 123 124 122不是合唱队形,因为前两名同学身高相等,不符合要求

123 122 121 122不是合唱队形,因为找不到一个同学,他的两侧同学身高递减。

你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。

注意:不允许改变队列元素的先后顺序  不要求最高同学左右人数必须相等

输入描述:

用例两行数据,第一行是同学的总数 N ,第二行是 N 位同学的身高,以空格隔开

输出描述:

最少需要几位同学出列

def left_max(l):
    dp = [1]*len(l)#若左边没有比自己小的数,则为自己本身,所以初始值为1
    for i in range(len(l)):
        for j in range(i):
            if l[j]

HJ52 计算字符串的编辑距离

Levenshtein 距离,又称编辑距离,指的是两个字符串之间,由一个转换成另一个所需的最少编辑操作次数。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。编辑距离的算法是首先由俄国科学家 Levenshtein 提出的,故又叫 Levenshtein Distance 。

例如:

字符串A: abcdefg

字符串B: abcdef

通过增加或是删掉字符 ”g” 的方式达到目的。这两种方案都需要一次操作。把这个操作所需要的次数定义为两个字符串的距离。

要求:

给定任意两个字符串,写出一个算法计算它们的编辑距离。

输入描述:

每组用例一共2行,为输入的两个字符串

输出描述:

每组用例输出一行,代表字符串的距离

##动态规划
while True:
    try:
        str1 = input()
        str2 = input()
        m = len(str1)
        n = len(str2)
        #创造二维数组n*m
        dp = [[1 for i in range(n+1)] for j in range(m+1)]
        for i in range(n+1):
            dp[0][i] = i
        for j in range(m+1):
            dp[j][0] = j
        for i in range(1,m+1):
            for j in range(1,n+1):
                if str1[i-1] == str2[j-1]:
                    dp[i][j] = dp[i-1][j-1]
                else:
                    dp[i][j] = min(dp[i-1][j-1],dp[i][j-1],dp[i-1][j])+1
        print(dp[m][n])       
    except:
        break
        
'''
# 不好理解,硬背吧
def func(str1,str2):
    lst = [[i+j for j in range(len(str2)+1)] for i in range(len(str1)+1)]
    for i in range(1,len(str1)+1):
        for j in range(1,len(str2)+1):
            if str1[i-1] == str2[j-1]:
                d = 0
            else:
                d = 1
            lst[i][j] = min(lst[i-1][j]+1,lst[i][j-1]+1,lst[i-1][j-1]+d)
    print(lst[len(str1)][len(str2)])
while 1:
    try:
        func(input(),input())
    except:
        break
'''        

你可能感兴趣的:(华为机试,python,leetcode)