问题描述
你有一架天平和 N 个砝码,这 N 个砝码重量依次是 W1,W2,⋅⋅⋅,WN。
请你计算一共可以称出多少种不同的重量? 注意砝码可以放在天平两边。
输入格式
输入的第一行包含一个整数 N。
第二行包含 N 个整数:W1,W2,W3,⋅⋅⋅,WN。
输出格式
输出一个整数代表答案。
样例输入
3
1 4 6
样例输出
10
思路:可以用模拟的方法,遍历每两个砝码之和,每两个砝码之差,所有砝码之和,再用set()去重,但是这样做不能通过全部测试用例,会运行超时
动态规划:
a[i-1]代表新加入这个砝码的重量,如果与这个未知量q相等,则dp值为1
dp[i-1]代表一个集合X(已知或者说已经测出来的数据集合),dp[i-1][a[i-1]+j]就表示,在集合X中是否有一个数等于a[i-1]+j,如果有则dp[i-1][a[i-1]+j]这个式子存在,令dp值为1。
dp[i-1][abs(a[i-1]-j)]表示在集合X中是否有一个数等于a[i-1]-j的绝对值,如果有则dp[i-1][abs(a[i-1]-j)]这个式子存在,令dp值为1
最后就是遍历dp表中为1的数,代表可以表示重量的个数
模拟:
n=int(input())
w=list(map(int,input().split()))
ans = set()
ans.add(w[0])
for i in w[1:]:
for j in ans.copy():#一个ans的复制
ans.add(i)
ans.add(i+j)
if j-i != 0:
ans.add(abs(j-i))#不取绝对值会出现负数
print(len(ans))
动态规划:
n=int(input())
a=list(map(int,input().split()))
sum=0
for i in range(n): #确定q的最大取值范围sum
sum+=a[i]
ans=0
dp=[[0]*2*sum for i in range(n+1)] #前列后行,只要行列满足最大范围即可,可*3或4等等
for i in range(1,n+1):
for j in range(1,sum+1):
dp[i][j]=dp[i-1][j] #如果i-1处的砝码就可以求出j的重量 那就不用执行下面判断
if dp[i][j]==0:
if a[i-1]==j or dp[i-1][a[i-1]+j] or dp[i-1][abs(a[i-1]-j)]:
dp[i][j]=1
for i in dp[n]:
if i != 0:
ans+=1
print(ans)