描述
现有n种砝码,重量互不相等,分别为 m1,m2,m3…mn ;
每种砝码对应的数量为 x1,x2,x3...xn 。现在要用这些砝码去称物体的重量(放在同一侧),问能称出多少种不同的重量。
注:称重重量包括 0
数据范围:每组输入数据满足 1≤𝑛≤10 , 1≤𝑚𝑖≤2000 , 1≤𝑥𝑖≤10
输入描述:
对于每组测试数据:
第一行:n --- 砝码的种数(范围[1,10])
第二行:m1 m2 m3 ... mn --- 每种砝码的重量(范围[1,2000])
第三行:x1 x2 x3 .... xn --- 每种砝码对应的数量(范围[1,10])
输出描述:
利用给定的砝码可以称出的不同的重量数
示例1
输入:
2 1 2 2 1
输出:
5
说明:
可以表示出0,1,2,3,4五种重量。
for堆砌
import sys
n = int(input())
wei_li = input().split()
num_li = input().split()
sum = {0}
for i in range(n):
li = []
for j in range(1,int(num_li[i])+1):
wei = int(wei_li[i])*j
li.append(wei)
temp = sum.copy()
for k in temp:
for l in li:
sum.add(k+l)
print(len(sum))
这里如果定义sum为列表,后面再转换为集合会报错:内存超限
集合的基础知识
集合内置方法完整列表如下:
一些牛人的方法
import sys # 导入sys模块
n = int(input()) # 从标准输入读取一个整数,并将其赋值给变量n
m = [int(i) for i in input().split(" ") if i] # 从标准输入读取一行,以空格分隔,转换为整数列表,并赋值给变量m
x = [int(i) for i in input().split(" ") if i] # 从标准输入读取另一行,以空格分隔,转换为整数列表,并赋值给变量x
mtype = {0} # 初始化一个包含元素0的集合mtype
for i in range(n): # 遍历范围为0到n-1的索引
for j in range(x[i]): # 根据x[i]的值,循环x[i]次
# 计算当前mtype中每个元素加上m[i]的值,并将结果与原始mtype集合取并集
mtype = {k+m[i] for k in mtype}.union(mtype)
print(len(mtype)) # 输出mtype集合的长度
集合推导式基本格式
{ expression for item in Sequence }或
{ expression for item in Sequence if conditional }
整体分析
该题实质是完全背包问题的一个变种,如果使用排列组合来找所有子集的方法时间复杂度高容易超时。(尝试过排列组合确实会很复杂)
使用动态规划算法解决
1. 定义状态:使用一个集合 possible_weights 来记录可能称出的所有重量。
2. 迭代每种砝码:对于每个砝码 m_i,在其对应的数量 x_i 之间进行迭代。 使用一个临时集合 new_weights 来保存当前迭代过程中产生的新重量。 对于现有的每个可能重量 w,添加 j * m_i(j 在 1 到 x_i 范围内),并将其添加到 new_weights 中。 最后,将 new_weights 中的所有重量添加到 possible_weights 中。
3. 计算所有可能重量:在完成所有砝码迭代后,possible_weights 应包含所有可能称出的重量。
4. 返回结果:possible_weights 的长度即为可能称出的不同重量数。 import sys
def count_possible_weights(n, weights, quantities):
# 初始化可能称出的重量
possible_weights = {0} # 初始化为空重,集合中只有一个元素0
# 迭代每种砝码
for i in range(n): # 遍历每种砝码
current_weight = weights[i] # 当前砝码的重量
current_quantity = quantities[i] # 当前砝码的数量
# 新的可能重量集合
new_weights = set() # 初始化一个新的集合来存储当前轮新增的可能重量
# 计算所有可能的重量
for w in possible_weights: # 遍历当前可能的所有重量
for j in range(1, current_quantity + 1): # 遍历当前砝码的数量
new_weight = w + j * current_weight # 计算新重量
new_weights.add(new_weight) # 将新重量加入新的集合
# 合并到可能重量集合中
possible_weights.update(new_weights) # 将新的可能重量合并到总的可能重量集合中
# 返回可能称出的不同重量数
return len(possible_weights) # 返回不同重量的数量
lines = [] # 初始化一个列表来存储输入数据
for line in sys.stdin: # 从标准输入读取数据
line = line.strip() # 去除每行的前后空格
if line == "": # 如果读取到空行,结束读取
break
lines.append([int(i) for i in line.split(" ")]) # 将每行的数据分割并转换为整数列表,加入lines列表中
for i in range(len(lines) // 3): # 处理每组输入数据,每组三行
n = lines[i * 3][0] # 第一行为砝码种类的数量
weights = lines[i * 3 + 1] # 第二行为每种砝码的重量列表
quantities = lines[i * 3 + 2] # 第三行为每种砝码的数量列表
print(count_possible_weights(n, weights, quantities)) # 调用函数并输出结果