@
題目 【80分】
你有一架天平和N個砝碼,這N個砝碼重量依次是W1,W2,……,WN請你計算一共可以稱出多少種不同的重量?
注意砝碼可以放在天平兩邊。
【樣例輸入】
3
1 4 6
【樣例輸出】
10
思路
這是一道動態規划題
- 確定dp數組(dp table)以及下標的含義
- 確定遞推公式
- dp數組如何初始化
- 確定遍歷順序
- 舉例推導dp數組
知識點
將dp初始化為0,二維數組
對於第一個加入的dp[i][array[0]]=1標記為能稱出的重量
最終dp:
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
第一次加入1,所以在dp[0,1] 這里標記為1
[0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0]
第二次加入4,所以在dp[1][4] 這里標記為1,之前的狀態為dp[0][1]也是為1,之后在加入4之后;4+1=5,所以dp[1][5]標記為1,abs(1-4)==3,所以dp[1][3]也標記為1;
[0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1]
同理:
所以最后求解個數的時候只需要將求解dp數組最后一行有多少個1,也就能得出答案
思路是沒問題,不過這道題最后兩個測試樣例超時了只有80分
代碼
n = int(input())
array = list(map(int, input().split()))
sum = sum(array)
a_len = len(array)
ans = 0
dp = [[0 for i in range(sum+1)] for j in range(a_len)]
dp[0][array[0]]=1 # no1
for i in range(1,a_len):
for j in range(1,sum+1):
dp[i][j]=dp[i-1][j] # copy 對於當前的復制前一個的重量
dp[i][array[i]]=1 # 當前狀態是可稱的
for j in range(1, sum+1): # 最大重量為所有砝碼重量總和
if(dp[i-1][j]): #pre=1 上一個狀態的重量
dp[i][j+array[i]] = 1 # 上一狀態的重量在加上當前重量
dp[i][abs(j-array[i])]=1 # 上一個狀態的重量減去當前狀態的重量
for i in range(1,sum+1):
if(dp[n-1][i]):
ans += 1
print(ans)