首页 > 试题广场 >

购物单

[编程题]购物单
  • 热度指数:421664 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
王强决定把年终奖用于购物,他把想买的物品分为两类:主件与附件,附件是从属于某个主件的,下表就是一些主件与附件的例子:
主件 附件
电脑 打印机,扫描仪
书柜 图书
书桌 台灯,文具
工作椅
如果要买归类为附件的物品,必须先买该附件所属的主件,且每件物品只能购买一次。
每个主件可以有 0 个、 1 个或 2 个附件。附件不再有从属于自己的附件。
王强查到了每件物品的价格(都是 10 元的整数倍),而他只有 N 元的预算。除此之外,他给每件物品规定了一个重要度,用整数 1 ~ 5 表示。他希望在花费不超过 N 元的前提下,使自己的满意度达到最大。
满意度是指所购买的每件物品的价格与重要度的乘积的总和,假设设第i件物品的价格为,重要度为,共选中了k件物品,编号依次为j_1,j_2,...,j_k,则满意度为:。(其中 * 为乘号)
请你帮助王强计算可获得的最大的满意度。




输入描述:

输入的第 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 是所属主件的编号)

 




输出描述:
 输出一个正整数,为张强可以获得的最大的满意度。
示例1

输入

1000 5
800 2 0
400 5 1
300 5 1
400 3 0
500 2 0

输出

2200
示例2

输入

50 5
20 3 5
20 3 5
10 3 0
10 2 0
10 1 0

输出

130

说明

由第1行可知总钱数N为50以及希望购买的物品个数m为5;
第2和第3行的q为5,说明它们都是编号为5的物品的附件;
第4~6行的q都为0,说明它们都是主件,它们的编号依次为3~5;
所以物品的价格与重要度乘积的总和的最大值为10*1+20*3+20*3=130       
只通过了80%用例,其他用例超时了,欢迎分享进一步剪枝方法。
def find_max(total_money, num, vs, ps, qs):
    max_v = 0
    selected_o = []
    def f(i, money, temp_v):
        nonlocal max_v
        if i == num or len(selected_o) == num:
            if temp_v > max_v:
                max_v = temp_v
            return
        else:
            # i is already selected
            if i in selected_o:
                f(i+1, money, temp_v)
            # i is not selected
            else:
                # i is main
                if qs[i] == 0:
                    if money >= vs[i]:
                        # select i
                        selected_o.append(i)
                        f(i+1, money-vs[i], temp_v+vs[i]*ps[i])
                        selected_o.pop()
                        # not select i
                        f(i+1, money, temp_v)
                    else:
                        f(i+1, money, temp_v)
                # i is not main
                else:
                    i_main = qs[i]-1
                    # i's main is selected
                    if i_main in selected_o:
                        if money >= vs[i]:
                            # select i
                            selected_o.append(i)
                            f(i+1, money-vs[i], temp_v+vs[i]*ps[i])
                            selected_o.pop()
                            # not select i
                            f(i+1, money, temp_v)
                        else:
                            f(i+1, money, temp_v)
                    # i's main is not selected
                    else:
                        if money >= vs[i] + vs[i_main]:
                            # select i and i's main
                            selected_o.append(i)
                            selected_o.append(i_main)
                            f(i+1, money-vs[i]-vs[i_main], temp_v+vs[i]*ps[i]+vs[i_main]*ps[i_main])
                            selected_o.pop()
                            selected_o.pop()
                            # not select i
                            f(i+1, money, temp_v)
                        else:
                            f(i+1, money, temp_v)
    f(0, total_money, 0)
    print(max_v)

while True:
    try:
        total_money, num = list(map(int, input().split()))
        vs = []
        ps = []
        qs = []
        for i in range(num):
            v, p, q = list(map(int, input().split()))
            vs.append(v)
            ps.append(p)
            qs.append(q)
        find_max(total_money, num, vs, ps, qs)
    except:
        break

发表于 2024-04-26 12:35:34 回复(0)
n, m = map(int, input().split())
sum=n
price=[[0]*3 for _ in range(m)]
man=[[0]*3 for _ in range(m)]
fu=[0]*m
flag=0
for i in range(m):
    a,b,c = map(int, input().split())
    fu[i]=c
    if c==0:
        flag+=1
        price[i][0]=a
        man[i][0]=a*b
    elif price[c-1][1]==0:
        price[c-1][1]=a
        man[c-1][1]=a*b
    else:
        price[c-1][2]=a
        man[c-1][2]=a*b
a1=int(n/10)+1
matr=[[0]*a1 for _ in range(flag+1)]
cor=0
for i in range(m):
    if fu[i]==0:
        cor+=1
        for k in range(a1):
            if k*10>=price[i][0]:
                matr[cor][k]=max(man[i][0]+matr[cor-1][k-price[i][0]//10],matr[cor-1][k])
                if k*10>=price[i][0]+price[i][1]:
                    matr[cor][k]=max(matr[cor][k],man[i][0]+man[i][1]+matr[cor-1][k-price[i][0]//10-price[i][1]//10],matr[cor-1][k])
                if k*10>=price[i][0]+price[i][2]:
                    matr[cor][k]=max(matr[cor][k],man[i][0]+man[i][2]+matr[cor-1][k-price[i][0]//10-price[i][2]//10],matr[cor-1][k])
                    if k*10>=price[i][0]+price[i][2]+price[i][1]:
                        matr[cor][k]=max(matr[cor][k],man[i][0]+man[i][2]+man[i][1]+matr[cor-1][k-price[i][0]//10-price[i][2]//10-price[i][1]//10],matr[cor-1][k])
            else:
                matr[cor][k]=matr[cor-1][k]
print(matr[flag][a1-1])

发表于 2024-03-22 21:26:31 回复(0)
简化了一下数据表
import sys
min_value = 10   # 这个主要简化数据量的大小
n, m = map(int, input().strip().split(' '))

# 主健列表,对应物品的价值 = 价格*重要性
v_list = [0 for i in range(m)]
w_list = [0 for i in range(m)]
# 附件列表
v1_list = {}
w1_list = {}

# 初始化
for i in range(m):
    v, p, q = map(int, input().strip().split(' '))
    if q == 0:
        # v_list.append(int(v // 10))
        # w_list.append(v * p)
        v_list[i] = int(v // min_value)
        w_list[i] = v * p
    else:
        if q-1 in w1_list:
            v1_list[q-1][1] = int(v // min_value)
            w1_list[q-1][1] = v * p
        else:
            v1_list[q-1] = [int(v // min_value), 0]
            w1_list[q-1] = [v * p, 0]

# print('主',v_list,w_list)
# print('主1',v1_list,w1_list)
# 这里开始循环遍历了

# col_num = 0
# 小于10啥也买不了,所有就不去列举了
col_num = int(n / min_value)  
dp = [[0 for i in range(col_num+1)], [0 for i in range(col_num+1)]]
# print(dp)
# dp 初始化
# 初始化
for j in range(col_num+1):
    # 如果金额大于第一件商品的金额
    if j >= v_list[0]:
        dp[0][j] = w_list[0]

    # 如果第一件商品存在附件需要判断其他情况了。
    if 0 in v1_list:

        if j >= v_list[0] + v1_list[0][0]:
            dp[0][j] = max(dp[0][j], w_list[0] + w1_list[0][0])

        if j >= v_list[0] + v1_list[0][1]:
            dp[0][j] = max(dp[0][j], w_list[0] + w1_list[0][1])


        if j >= v_list[0] + v1_list[0][0] + v1_list[0][1]:
            dp[0][j] = max(dp[0][j], w_list[0] + w1_list[0][0] + w1_list[0][1])


# 处理剩余元素
for i in range(1, len(v_list)):
    for j in range(col_num+1):
        # 不选
        x = dp[(i - 1) & 1][j]
        # 选
        if j >= v_list[i]:
            y = dp[(i - 1) & 1][j - v_list[i]] + w_list[i]
        else:
            y = 0

        if i in v1_list:
            if j >= v_list[i] + v1_list[i][0]:
                y = max(y, dp[(i - 1) & 1][j - v_list[i] - v1_list[i][0]] + w_list[i] + w1_list[i][0])

            if j >= v_list[i] + v1_list[i][1]:
                y = max(y, dp[(i - 1) & 1][j - v_list[i] - v1_list[i][1]] + w_list[i] + w1_list[i][1])

            if j >= v_list[i] + v1_list[i][0] + v1_list[i][1]:
                y = max(y, dp[(i - 1) & 1][j - v_list[i] - v1_list[i][0] - v1_list[i][1]] + w_list[i] + w1_list[i][0] + w1_list[i][1])
        # 取两者中的最大值
        dp[i & 1][j] = max(x, y)
        # print(dp)

# print(dp,(len(v_list) - 1),(len(v_list) - 1) & 1,col_num,dp[0])
print(dp[(len(v_list) - 1) & 1][col_num])




编辑于 2024-03-14 19:59:18 回复(0)
import sys

line = [i.strip('\n').split() for i in sys.stdin.readlines()]
all_money, buy_num = line[0]

d = [[0 for j in range(0, int(all_money)+1)] for i in range(len(line))]

'''将主件与附件一一对应'''
k = {}
for index,i in enumerate(line):
    if len(i) > 2 and i[-1] != "0":
        if int(i[-1]) not in k.keys():
            k[int(i[-1])] = {}
        if k[int(i[-1])]:
            k[int(i[-1])]["附件2"] = i[:2]
        else:
            k[int(i[-1])]["附件1"] = i[:2]

for i in range(1, len(line)):
    for j in range(10, len(d[0]), 10):
        # if i >=4:
        #     print(i, j)
        if line[i][-1] != "0":
            d[i][j] = d[i-1][j]
        elif i in k.keys():
            if len(k[i]) == 2:
                
                d[i][j] = max(d[i-1][j], # 不选该主件
                d[i-1][j-int(line[i][0])] + int(line[i][0]) * int(line[i][1]) if j-int(line[i][0]) >=0 else 0, # 只选一个主件
                d[i-1][j-int(line[i][0]) - int(k[i]["附件1"][0])] + int(line[i][0]) * int(line[i][1]) +int(k[i]["附件1"][0]) * int(k[i]["附件1"][1])  if j-int(line[i][0])- int(k[i]["附件1"][0]) >=0 else 0,# 选一个主件一个附件1
                d[i-1][j-int(line[i][0]) - int(k[i]["附件2"][0])] + int(line[i][0]) * int(line[i][1]) +int(k[i]["附件2"][0]) * int(k[i]["附件2"][1])  if j-int(line[i][0])- int(k[i]["附件2"][0]) >=0 else 0,# 选一个主件一个附件2
                d[i-1][j-int(line[i][0]) - int(k[i]["附件1"][0])-int(k[i]["附件2"][0])] + int(line[i][0]) * int(line[i][1])+int(k[i]["附件1"][0]) * int(k[i]["附件1"][1])+int(k[i]["附件2"][0]) * int(k[i]["附件2"][1]) if j-int(line[i][0])- int(k[i]["附件1"][0]) -int(k[i]["附件2"][0]) >=0 else 0,# 选一个主件两个附件
                )
            else:
                d[i][j] = max(d[i-1][j], # 不选该主件
                d[i-1][j-int(line[i][0])] + int(line[i][0]) * int(line[i][1]) if j-int(line[i][0]) >=0 else 0, # 只选一个主件
                d[i-1][j-int(line[i][0]) - int(k[i]["附件1"][0])] + int(line[i][0]) * int(line[i][1]) +int(k[i]["附件1"][0]) * int(k[i]["附件1"][1])  if j-int(line[i][0])- int(k[i]["附件1"][0]) >=0 else 0)# 选一个主件一个附件1
        else: # 说明该主件没有附件
            d[i][j] = max(d[i-1][j], # 不选该主件
                d[i-1][j-int(line[i][0])] + int(line[i][0]) * int(line[i][1]) if j-int(line[i][0]) >=0 else 0) # 只选一个主件
        
        
print(d[-1][-1])

编辑于 2024-03-13 11:27:38 回复(0)
谢谢大佬,提交通过了,不过重点地方的迭代优化为什么可以这么写还是不太明白惹
while True:
    try:
        total, N = map(int, input().split())  #将传⼊的函数变量 func 作⽤到 lst 变量的每个元素中
        total = total // 10
        items = {}  #定义字典存储数据
        item_acc = {}
        for i in range(N):
            price, weight, indx = map(int, input().split()) 
            price = price // 10
            if indx == 0:
                items[i+1] = [[price,weight*price]]
            else:
                item_acc[i+1] =[[indx,price,weight]]

        for key in item_acc:
            for indx,price, weight in item_acc[key]:
                new = [[item[0] + price, item[1] + price * weight] for item in items[indx]]
                items[indx].extend(new)

        dp = [0] * (total + 1)
        # print(items)
        for key in items:
            for j in range(total, 0,-1):
                for price, weight in items[key]:
                    if price <= j <= total:
                        dp[j] = max(weight + dp[j - price], dp[j])
        print(10 * max(dp))
    except:
        break


编辑于 2024-02-29 14:23:02 回复(0)
import math

# 接收输入信息
n_m_list = str(input()).split(" ")
n = int(n_m_list[0])
m = int(n_m_list[1])

v_p_q_list = []
for i in range(m):
    v_p_q_list.append([int(v_p_q) for v_p_q in str(input()).split(" ")])
# 新建存储结构, 用于将主件和附件统一起来
# {q: {'principal': (v, p), 'annex': [(v, p), (v, p)]}, ...}
principal_annex_dict = dict()
# 增加排序, 以确保主件在前

for i, v_p_q in enumerate(v_p_q_list):
    i = i + 1
    v, p, q = v_p_q
    if q == 0:
        if i in principal_annex_dict:
            principal_annex_dict[i]["principal"] = (v, p)
        else:
            principal_annex_dict[i] = dict(principal=(v, p), annex=[])
    else:
        if q in principal_annex_dict:
            principal_annex_dict[q]["annex"].append((v, p))
        else:
            principal_annex_dict[q] = dict(principal=None, annex=[(v, p)])
# 主要部件数量
key_list = [key for key in principal_annex_dict]
key_list.sort(key=lambda x: len(principal_annex_dict[x]['annex']))
principal_len = len(principal_annex_dict)
price_len = math.floor(n / 10) + 1
matrix = [[0 for _ in range(price_len)] for _ in range(principal_len + 1)]


def get_weight(price_now, price, line, weight_now):
    if price_now - price * 10 > 0:
        return matrix[line - 1][price]
    else:
        # 说明可以买, 需要分情况看怎么买
        num_up = matrix[line - 1][price]
        num_now = matrix[line - 1][price - int(price_now / 10)] + weight_now
        return max(num_up, num_now)


for price in range(1, price_len):
    for i, key in enumerate(key_list):
        line = i + 1
        # 判断当前价格是否大于金额, 小于则不能购买, 最优解等于上一行价格
        v, p = principal_annex_dict[key]["principal"]
        annex = principal_annex_dict[key]["annex"]
        temp_list = []
        price_now = v
        weight_now = v * p
        temp_list.append(get_weight(price_now, price, line, weight_now))
        # 增加附件的判断, 分三种情况, 主副1, 主副2, 主副1副2
        if len(annex) >= 1:
            # 主副1
            v_annex, p_annex = annex[0]
            price_now = v + v_annex
            weight_now = v * p + v_annex * p_annex
            temp_list.append(get_weight(price_now, price, line, weight_now))

        if len(annex) == 2:
            # 主副2
            v_annex, p_annex = annex[1]
            price_now = v + v_annex
            weight_now = v * p + v_annex * p_annex
            temp_list.append(get_weight(price_now, price, line, weight_now))
            # 主副1副2
            v_annex_1, p_annex_1 = annex[0]
            v_annex_2, p_annex_2 = annex[1]
            price_now = v + v_annex_1 + v_annex_2
            weight_now = v * p + v_annex_1 * p_annex_1 + v_annex_2 * p_annex_2
            temp_list.append(get_weight(price_now, price, line, weight_now))

        matrix[line][price] = max(temp_list)
# 打印输出数据
print(matrix[principal_len][price_len - 1])


编辑于 2024-02-28 19:07:15 回复(0)
#贡献一个不用字典纯用列表的做法
tmp = input().split()
money = int(tmp[0])
m = int(tmp[-1])
flag = 10
a=[]
b= []
z = 1
#将主件和附件存为两个双重列表a,b,主件列表的最后增加序号元素用以识别附件
for i in range (m):
    s = input().split()
    for j in range(3):
        s[j] = int(s[j])
    if s[2] == 0:      
        a.append(s)   #是主件的话存a
        a[-1] = a[-1] + [z]
        z += 1
    else:
        b.append(s)   #是附件的话存b
        z += 1        #不管是别到的是主件还是附件序号都要加1
for i in range(len(b)):#将附件存在对应序号的主件
    for j in range(len(a)):
        if b[i][2] == a[j][-1]:#主件列表最后的序号元素匹配附件列表第三个元素(最后一个)
            a[j] = a[j] + b[i]#对应主件的附件增加到主件列表
for j in range(len(a)):
    a[j].pop(3)       #去除序号元素以便后续处理每个主件列表
d=[]
def gaibian(list:list):#参数为每个主件列表,因为每个附件必须先买主件,因此将同一主的所有主附可能性生成为新的列表d
    moneytmp = 0
    satisfy = 0
    c= []
    moneytmp = list[0]
    if moneytmp <= money:#主件是否符合money要求
        satisfy = list[0]*list[1]
        c = c + [moneytmp,satisfy]
    for j in range(3,len(list),3):#主件和附件有多少符合要求的组合,这里写的好像有问题将就着看吧
        moneytmp = moneytmp + list[j]
        if moneytmp <= money:
            satisfy = satisfy + list[j]*list[j+1]
            c = c + [moneytmp,satisfy]#将所有主附搭配的money和满意度重新赋值给新的列表
    if(c != []):         #光是主件就不符合的情况直接排除
        d.append(c)
for i in range(len(a)):
    gaibian(a[i])        #将所有主件列表进行生成新的双重列表d,d的含义为每个主件种类,对应的所有money符合要求的主附组合(money,满意度)
def diedai(list):        #
    c = []
    moneytmp = 0
    satisfy = 0
    if len(list)==1:
        return list      #迭代退出条件
    else:
        for i in range(0,len(list[0]),2):
            for j in range(0,len(list[1]),2): #每次迭代使得两个不同主件对应的(money,满意度)组合合成在一个列表中
                moneytmp =  list[0][i] + list[1][j]  
                if moneytmp <= money:
                    satisfy = list[0][i+1]+list[1][j+1]
                    c= c+[moneytmp,satisfy]   #俩主件的组合由 每一个主件的任一主附组合和另一个主件的任一主附组合加起来组成的新的组合,且满足money要求
        c = c+list[0]+list[1]                 #再加上两个主件自己的任一主附组合等于两个主件所有可能的满足money要求的组合
        list.pop(0)                          #使用完就可以pop掉单一主件的所有可能性
        list.pop(0)
        list.insert(0,c)                     #增添新的组合
        return diedai(list)                  #迭代即参数变化后用同样的逻辑处理
e = diedai(d)                   
print(e)
h = max(e[0][i] for i in range(len(e[0])))   #在所有的组合中找到最大值,即为最大满意度
print(h)  

编辑于 2024-02-23 22:01:38 回复(0)
# 先看《算法图解》背包问题章节,再看python3 题解置顶大佬篇,梳理思路嘎嘎清晰:
n, m = map(int,input().split())  #给每个输入值强制转换为int型
primary, annex = {}, {}
for i in range(1,m+1):  #存当前输入的数据
    x, y, z = map(int, input().split())
    if z==0:#表示当前输入的数据q是个主件
        primary[i] = [x, y]
    else:#表示当前输入的数据q是个附件
        if z in annex:#第二个附件
            annex[z].append([x, y])
        else:#第一个附件
            annex[z] = [[x,y]]
m = len(primary)#主件个数转化为可以放进背包的物品个数
dp = [[0]*(n+1) for _ in range(m+1)]#开辟背包空间:m(行) * n(列)
w, v= [[]], [[]]
for key in primary:  #将当前存好的数据放到w,v两个二维列表中
    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])
        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])
            w_temp.append(w_temp[0]+annex[key][0][0]+annex[key][1][0])#既带附件1又带附件2进背包
            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)
    v.append(v_temp)
for i in range(1,m+1):
    for j in range(10,n+1,10):#物品的价格是10的整数倍,步长设为10,动态规划,缩小数据v的数量级
        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]) #0-1背包拓展,递归
        dp[i][j] = max_i #中间变量归位,供下一趟循环时使用
print(dp[m][n])   #递归调用dp


编辑于 2024-01-24 23:47:58 回复(0)
虽然结果正确,但是(8/12)超时了
n, m = input().split()
n, m = int(n), int(m)
l, ln = [], []
d = {}
for i in range(m):
    l.append(input().split())
for k, v in enumerate(l):
    if v[-1] == "0":
        ln.append({'v': int(v[0]), 'p': int(v[1]), 'q': []})
        for kj, j in enumerate(l):
            if int(j[-1]) == k + 1:
                ln[-1]['q'].append({'v': int(j[0]), 'p': int(j[1])})


def r(ls=[], ns=0, ms=0, my=0, mys=0, p=[]):
    lc = ls.copy()
    for index in range(len(ls)):
        i = ls[index]
        lc.pop(0)
        ns += i['v']
        ms += 1
        my += i['v'] * i['p']
        if ns < n and ms < m:
            if 'q' in i and len(i['q']) != 0:
                mys = r(i['q'] + lc, ns, ms, my, mys, p)
            else:
                mys = r(lc, ns, ms, my, mys, p)
        mys = my if ns <= n and ms <= m and my > mys else mys
        ns -= i['v']
        ms -= 1
        my -= i['v'] * i['p']

    return mys


print(r(ln))


编辑于 2023-12-10 01:50:45 回复(1)
class way:

    def __init__(self,money,num) -> None:
        self.items = []
        self.money = money
        self.price=0
        self.value=0
        self.num = num
    
    def add(self,product):
        if product[0] in self.items:
            return False
        if product[3]==0&nbs***bsp;product[3]-1 in self.items:
            a0 = self.price + product[1]
            if a0 <=money:
                self.items.append(product[0])
                self.price=a0
                self.value=self.value+product[1]*product[2]
                return True
        return False
def way_copy(a):
    a0 = way(a.money,a.num)
    a0.items = a.items.copy()
    a0.price = a.price
    a0.value = a.value
    return a0

def try_add(wayin,products):       
    way0 = way_copy(wayin)
    waymax = way_copy(wayin)
    #print(id(way0.items),id(wayin.items))
    #print(id(wayin),id(way0),id(waymax))
    for i in  range(wayin.num):
        if wayin.add(products[i]):
            if wayin.value>waymax.value:
                waymax=way_copy(wayin)
            way1=try_add(wayin,products)
            if way1.value>waymax.value:
                waymax=way_copy(way1)
            wayin = way_copy(way0)
    return waymax

x = input().split()
money = int(x[0])
m = int(x[1])
products = {}
for i in range(m):
    x = input().split()
    products[i]=[i,int(x[0]),int(x[1]),int(x[2])]
way0 =way(money,m)
print(try_add(way0,products).value)
5/12组超时,意料之中。没看背包问题说明之前想到的递归,时间复杂度n的n次方了。谁知道说明中的时间复杂度mn是什么意思
发表于 2023-11-25 20:24:11 回复(0)
#我也记录一下未完成的思路
import itertools as it
s=input().strip().split(' ')
n=int(s[0])
m=int(s[1])
vst=[]
pst=[]
qst=[]
for i in range(m):
    s=input().strip().split(' ')
    vst.append(int(s[0]))
    pst.append(int(s[1]))
    qst.append(int(s[2]))
def vw(index): #满意度
    return vst[index] * pst[index]

def vw1(index):#只选主件
    if qst[index] == 0:
        return vw(index)
    return 0

def vw2(index):#选主件和附件1
    fj=0
    for i,q in enumerate(qst):
        if q == index :
            fj=vw(i)
            break
    zj = vw1(index)
    if zj > 0 :
        return fj + zj
    return 0

def vw3(index):#选主件和附件2
    fj=0
    j=0
    for i,q in enumerate(qst):
        if q == index :
            j+=1
            if j == 2 :
                fj=vw(i)
                break
    zj = vw1(index)
    if zj > 0 :
        return fj + zj
    return 0

def vw4(index):#选主件和附件1,2
    fj=0
    j=0
    for i,q in enumerate(qst):
        if q == index :
            j+=1
            if j <= 2 :
                fj += vw(i)
                if j==2 :break
    zj = vw1(index)
    if zj > 0 :
        return fj + zj
    return 0
class cls():
    def __init__(self,index,kind=-1) -> None:
        self.index = index
        self.kind = kind
    def set_kind(self,kind):
        self.kind = kind
    def get_first_index(self):
        for i,q in enumerate(qst):
            if q == self.index :
                return i
        return -1
    def get_second_index(self):
        j=0
        for i,q in enumerate(qst):
            if q == self.index :
                j+=1
                if j== 2 : return i
        return -1
    def get_m(self):#获得选择方案的件数
        if self.kind <= 0 :
            return self.kind +1
        elif 1<= self.kind <=2:
            if self.index in qst:
                return 2
            else:
                return 1
        elif self.kind == 3:
            j=0
            for i in qst:
                if qst[i] == self.index :
                    j +=1
            return j + 1
    def get_v(self):#获得选择方案的总价格
        if self.kind < 0 :
            return 0
        elif self.kind == 0 :
            return vst[self.index]
        elif self.kind == 1 :
            i = self.get_first_index()
            if i >= 0 :
                return vst[self.index] + vst[i]
            else:
                return vst[self.index]
        elif self.kind == 2 :
            i = self.get_second_index()
            if i >= 0 :
                return vst[self.index] + vst[i]
            else:
                return vst[self.index]
        elif self.kind == 3:
            i = self.get_first_index()
            j = self.get_second_index()
            v = vst[self.index]
            if i >= 0 : v += vst[i]
            if j >= 0 : v += vst[j]
            return v
    def get_vw(self):#获得方案总满意度
        if self.kind == -1:
            return 0
        elif self.kind == 0:
            return vw1(self.index)
        elif self.kind == 1:
            return vw2(self.index)
        elif self.kind == 2:
            return vw3(self.index)
        elif self.kind == 3:
            return vw4(self.index)

zjfa=[]
for i,q in enumerate(qst):
    if q == 0 :
        zjfa.append(cls(i))
max = 0

lst=[-1,0,1,2,3]
ast=[i for i in it.permutations(lst,len(zjfa))]
for item in ast:
    for i,c in enumerate(zjfa):
        c.set_kind(item[i])
    mv = 0
    vv = 0
    mm = 0
    for c in zjfa:
        vv += c.get_v()
        mm += c.get_m()
        if vv <= n and mm <=m:
            mv += c.get_vw()
    if max < mv : max = mv
     
print(max)
       

发表于 2023-10-25 17:46:50 回复(0)
# 0-1背包问题扩展

# 读取输入
N,m = map(int,input().split())

# 由于金额为10的倍数,从而动态规划时可以先除以10,减小计算复杂度
N = N//10

# 初始化存储主件的字典
vpq_d = dict()
# 初始化存储主件映射附件的字典
relation = dict()
# 依次读取物件信息
for i in range(m):
    # 读取金额,重要度,标识
    v,p,q = map(int,input().split())
    # 如果该物件不是主件
    if q != 0:
        # relation字典不存在该键时初始化
        if not isinstance(relation.get(q),list):
            relation[q] = [[v//10,p]]
        else:
            # 存储主附件映射信息,键为主件序号,值为各附件信息
            relation[q].append([v//10,p])
    else:
        # 存储主件信息
        vpq_d[i+1] = [v//10,p]

# 初始化二维数组,用以进行动态规划,注意列表的指向问题,谨慎使用*
# 利用主件数量作为二维数组的行
dp = [[0]*(N+1) for _ in range(len(vpq_d)+1)]
# 创建变量存储主件的序号
main = list(vpq_d.keys())

# 外循环为二维数组的列
for i in range(1,len(dp)):
    # 内循环为二维数组的行
    for j in range(1,len(dp[0])):
        # 首先判断该主件金额是否大于当前金额j
        if vpq_d[main[i-1]][0]>j:
            # 大于则最大满意度为dp[i-1][j]
            dp[i][j] = dp[i-1][j]
        # 继续判断该主件是否存在附件
        elif main[i-1] not in relation.keys():
            # 若存在附件,则计算两种可能性性的最大值作为最大满意度
            ## 1.dp[i-1][j-v]+v*w
            ## 2. dp[i-1][j]
            dp[i][j] = max(dp[i-1][j-vpq_d[main[i-1]][0]]+vpq_d[main[i-1]][0]*vpq_d[main[i-1]][1],dp[i-1][j])
        else:
            # 以下情况均为该主件存在附件
            # 若只购买主件
            a = dp[i-1][j-vpq_d[main[i-1]][0]]+vpq_d[main[i-1]][0]*vpq_d[main[i-1]][1]
            # 若购买主件和一个附件
            f = []
            for k in range(len(relation[main[i-1]])):
                if (vpq_d[main[i-1]][0] + relation[main[i-1]][k][0])<=j:
                    f.append(dp[i-1][j-vpq_d[main[i-1]][0]-relation[main[i-1]][k][0]]+vpq_d[main[i-1]][0]*vpq_d[main[i-1]][1]+relation[main[i-1]][k][0]*relation[main[i-1]][k][1])
            b = 0 if not f else max(f)
            # 若所有附件全购买,最多为两个,若没有两个则令其为0
            if len(relation[main[i-1]]) == 2 and (vpq_d[main[i-1]][0] + relation[main[i-1]][0][0] + relation[main[i-1]][1][0])<=j:
                c = dp[i-1][j-vpq_d[main[i-1]][0]-relation[main[i-1]][0][0]-relation[main[i-1]][1][0]]+vpq_d[main[i-1]][0]*vpq_d[main[i-1]][1]+relation[main[i-1]][0][0]*relation[main[i-1]][0][1]+relation[main[i-1]][1][0]*relation[main[i-1]][1][1]
            else:
                c = 0
            # 计算以上三种情况的最大满意度作为dp[i][j]
            dp[i][j] = max(a,b,c,dp[i-1][j])

# 打印二位数值dp[len(vpq_d)][N],即为题目中的最大满意度
# 注意前面金额都除以10了,所以最后结果要乘以10
print(dp[len(vpq_d)][N]*10) 
发表于 2023-10-16 18:29:01 回复(0)
重点是附件只有 0个 1个 或者 2个,不会有更多,太坑了,以为会有很多个还得选来选去搜索空间增加太多,
在附件问题上附件数量少直接暴力了

mm, nn = input().split()

mm, nn = int(mm), int(nn)

maxx = mm//10

spa =  [ [0,0,0] for i in range(nn) ]

zhujian = []

value = [0 for i in range(maxx+1)]


for i in range(nn):
    a, b, c = input().split()
    a, b, c = int(a), int(b), int(c)
    spa[i][0] = a
    spa[i][1] = b
    spa[i][2] = c
    if c == 0 :
        zhujian.append( i )

for zjnum in zhujian: 
    fjcount = 0
    fj = [    [0,0], [0,0] ]
    for i in range(nn):
        if spa[i][2] == zjnum+1:
            # print( fjcount,zjnum)
            fj[fjcount][0] = spa[i][0]
            fj[fjcount][1] = spa[i][1]   
            fjcount += 1  
            
    
    low = spa[zjnum][0] // 10
    val = spa[zjnum][0]*spa[zjnum][1]

    if fjcount >= 1:
        low1 = spa[zjnum][0] // 10 + fj[0][0] // 10
        val1 = spa[zjnum][0]*spa[zjnum][1] + fj[0][0]*fj[0][1]

    if fjcount == 2:
        low2 = spa[zjnum][0] // 10 + fj[1][0] // 10
        val2 = spa[zjnum][0]*spa[zjnum][1] + fj[1][0]*fj[1][1]
        
        low3 = spa[zjnum][0] // 10 + fj[0][0] // 10 + fj[1][0] // 10
        val3 = spa[zjnum][0]*spa[zjnum][1] + fj[0][0]*fj[0][1] + fj[1][0]*fj[1][1]
    
    for j in range(maxx,low-1,-1):
        value[j] = max( value[j], value[j-low]+val )
        if fjcount == 1:
            if j >= low1 :
                value[j] = max( value[j], value[j-low1]+val1 )
        if fjcount ==2:
            if j >= low1 :
                value[j] = max( value[j], value[j-low1]+val1 ) 
            if j >= low2 :
                value[j] = max( value[j], value[j-low2]+val2 )
            if j >= low3 :
                value[j] = max( value[j], value[j-low3]+val3 )

print(value[maxx])

 
发表于 2023-09-07 03:37:56 回复(0)
记录未完成思路
import sys
l1=[]
l2=[]
l3=[]
for line in sys.stdin:
    a = line.split()
    l1.append(int(a[0]))
    l2.append(int(a[1]))
    if len(a) == 3:
        l3.append(int(a[2]));
# l4=l1[1:]
# l5=l2[1:]
# for k in range(len(l4)):
#     dit1[k] = int(l4[k]);
#     dit2[k] = int(l5[k]);
#     dit3[k] = int(l3[k]);
#     if dit3[k] >=1:
#         dit1[k]+=dit1[dit3[k]]
    
for i in range(len(l3)):
    if l3[i]>0:
        l1[i+1]+=l1[l3[i]]
    l3[i]+=1

# print(l1)
# print(l2)
# print(l3)
# print(l4)
money = l1[0]
nums = l2[0]
datas = l1[1:]
datas_num = l3
perfect = l2[1:]
# print(money,nums,datas,datas_num)

for i in range(len(datas)):
    for j in range(len(datas)):
        if datas[i]+datas[j] <= money and datas_num[i]+datas_num[j]<=nums and i<j:
            print(perfect[i]*datas[i]+perfect[j]*datas[j])

     


发表于 2023-08-03 17:20:15 回复(0)

问题信息

难度:
43条回答 100703浏览

热门推荐

通过挑战的用户

查看代码