题解 | #购物单#

购物单

https://www.nowcoder.com/practice/f9c6f980eeec43ef85be20755ddbeaf4

inline1 = input().split(' ')
N = int(inline1[0])
m = int(inline1[1])

staffs = []
for i in range(m):
    inline2 = input().split(' ')
    v = int(inline2[0])
    p = int(inline2[1])
    q = int(inline2[2])
    staffs.append([v, p, q])

primes = {}
addts = {}
staffs_dict = {}

for i, ele in enumerate(staffs):
    staffs_dict[i] = ele

for k, v in staffs_dict.items():
    if not v[-1]:
        primes[k+1] = v[:-1]
    else:
        if v[-1] not in addts.keys():
            addts[v[-1]] = [v[:-1]]
        else:
            addts[v[-1]].append(v[:-1])

dp_arr = []
for av_num in range(1, len(primes)+1): 
    dp_arr.append([])
    for tens in range(1, N//10+1):
        dp_arr[-1].append(0)


for av_num in range(len(primes)):
    # print(av_num, primes)
    cur_staff = primes.popitem()
    idx = cur_staff[0]
    cur_prime = cur_staff[1]
    if idx in addts.keys():
        cur_addt = addts[idx]
        cur_comp = []
        if len(cur_addt) == 1:  # 对主从物品的多种可能组合进行建模
            cur_comp = [[cur_prime[0], cur_prime[0]*cur_prime[1]], 
                        [cur_prime[0]+cur_addt[0][0], cur_prime[0]*cur_prime[1]+cur_addt[0][0]*cur_addt[0][1]]]  # [[cur_prime], [cur_prime, cur_addt[0]]]
        elif len(cur_addt) == 2:  # 对主从物品的多种可能组合进行建模
            cur_comp = [[cur_prime[0], cur_prime[0]*cur_prime[1]], 
                        [cur_prime[0]+cur_addt[0][0], cur_prime[0]*cur_prime[1]+cur_addt[0][0]*cur_addt[0][1]], 
                        [cur_prime[0]+cur_addt[1][0], cur_prime[0]*cur_prime[1]+cur_addt[1][0]*cur_addt[1][1]], 
                        [cur_prime[0]+cur_addt[0][0]+cur_addt[1][0], cur_prime[0]*cur_prime[1]+cur_addt[0][0]*cur_addt[0][1]+cur_addt[1][0]*cur_addt[1][1]]]
    else:
        cur_comp = [[cur_prime[0], cur_prime[0]*cur_prime[1]]]
    for tens in range(N//10):
        cash = (1+tens)*10
        if tens > 0 and av_num > 0:  # dp_arr初始化,状态转移(比较大小)从初始化状态开始,初始化状态从左、上状态获得
            dp_arr[av_num][tens] = max(dp_arr[av_num][tens-1], dp_arr[av_num-1][tens])  # initialization
        elif tens > 0 and av_num == 0:  # dp_arr初始化,状态转移(比较大小)从初始化状态开始,初始化状态从左、上状态获得
            dp_arr[av_num][tens] = dp_arr[av_num][tens-1]  # initialization
        elif tens == 0 and av_num > 0:  # dp_arr初始化,状态转移(比较大小)从初始化状态开始,初始化状态从左、上状态获得
            dp_arr[av_num][tens] = dp_arr[av_num-1][tens]
        if av_num == 0:
            for comp in cur_comp:  # 对每一种主从组合,都进行一次01背包的状态转移
                # print(comp[0], cash)
                if comp[0] <= cash:
                    dp_arr[av_num][tens] = max(dp_arr[av_num][tens], comp[1])
        else:
            for comp in cur_comp:  # 对每一种主从组合,都进行一次01背包的状态转移
                if comp[0] == cash:
                    dp_arr[av_num][tens] = max(dp_arr[av_num][tens], comp[1])
                elif comp[0] < cash:
                    dp_arr[av_num][tens] = max(dp_arr[av_num][tens], dp_arr[av_num-1][(cash-comp[0])//10-1]+comp[1])
print(dp_arr[len(primes)-1][N//10-1])

01背包问题的拓展,如果对附属品和主物品同等级对待,那么就会在加入附属品时考虑是否已加入主物品,很麻烦。附属品可以看做是对某一个物品的升级,建模为该种物品的多种可能性,在dp时对每一种可能性都进行一次01背包问题的状态转移。这样就保证了附属品的加入在主物品加入的前提之下。

全部评论

相关推荐

10-18 13:01
已编辑
西安理工大学 C++
小米内推大使:建议技能还是放上面吧,hr和技术面试官第一眼想看的应该是技能点和他们岗位是否匹配
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务