Solve 100 past questions that beginners and intermediates should solve in Python. The goal is to turn light blue by the time you finish solving everything.
This article is "039-045 Dynamic Programming: Knapsack DP Variants".
The problem can be solved if you can actually write the target dp
table, but it is difficult to solve if you can not imagine the table.
N = int(input())
num = list(map(int, input().split()))
dp = [[0] * (N-1) for _ in range(21)]
for i in range(21):
if i == num[0]:
dp[i][0] = 1
for j in range(1, N-1):
for i in range(21):
if dp[i][j-1] <= 0:
continue
if i - num[j] >= 0:
dp[i - num[j]][j] += dp[i][j-1]
if i + num[j] <= 20:
dp[i + num[j]][j] += dp[i][j-1]
answer = dp[num[-1]][N-2]
print(answer)
The dp table matches the row subscript with the calculated total value, the column subscript with the given integer subscript. In the dp table, record "the number of cases where the calculation result is exactly i by column j".
The dp table created in Input Example 1 is as follows. The answer is dp [8] [9](= 10).
0 1 2 3 4 5 6 7 8 9
0 0 0 0 0 0 0 1 2 4 8
1 0 0 0 0 1 0 0 0 0 0
2 0 0 0 0 0 1 1 3 6 12
3 0 0 1 1 1 0 0 0 0 0
4 0 0 0 0 0 1 2 4 8 8
5 0 1 0 1 1 0 0 0 0 0
6 0 0 0 0 0 1 3 5 10 12
7 0 0 1 1 0 0 0 0 0 0
8 1 0 0 0 0 2 3 4 8 10
9 0 0 1 1 1 0 0 0 0 0
10 0 0 0 0 0 2 4 6 12 12
11 0 1 0 1 1 0 0 0 0 0
12 0 0 0 0 0 2 2 4 8 10
13 0 0 1 1 1 0 0 0 0 0
14 0 0 0 0 0 0 3 6 12 10
15 0 0 0 0 1 0 0 0 0 0
16 0 0 0 0 0 1 1 3 6 8
17 0 0 0 1 1 0 0 0 0 0
18 0 0 0 0 0 1 2 3 6 12
19 0 0 0 0 1 0 0 0 0 0
20 0 0 0 0 0 1 1 1 2 8
I think it's a good idea to write this table first and then write the code that realizes this table. I imagine that once you get used to it, you'll be able to write code directly without writing this table, but I can't solve it without writing a table yet.
N, K = map(int, input().split()) #K days out of N days have already been decided
pastas = [0] * (N+1)
for _ in range(K):
A, B = map(int, input().split())
pastas[A] = B
dp = [[0] * (N+1) for _ in range(4)]
MOD = 10**4
dp[1][0] = 1
for j in range(1, N+1):
if pastas[j] == 0:
for i in range(1, 4):
for k in range(1, 4):
dp[i][j] += dp[k][j-1]
for i in range(1, 4):
if j -2 > 0 and dp[i][j-1] > 0 and dp[i][j-2] > 0:
dp[i][j-1] -= dp[i][j-2] #Subtract the one 2 days ago so that it does not continue for 3 days or more
dp[i][j] -= dp[i][j-2] #Subtract the one 2 days ago so that it does not continue for 3 days or more
else:
for k in range(1, 4):
dp[pastas[j]][j] += dp[k][j-1]
if j - 2 > 0 and dp[pastas[j]][j-1] > 0 and dp[pastas[j]][j-2] > 0:
dp[pastas[j]][j-1] -= dp[pastas[j]][j-2] #Subtract the one 2 days ago so that it does not continue for 3 days or more
dp[pastas[j]][j] -= dp[pastas[j]][j-2] #Subtract the one 2 days ago so that it does not continue for 3 days or more
answer = 0
for i in range(1, 4):
answer += dp[i][-1]
print(answer % MOD)
There is a feeling that it was forcibly solved, but it is AC above.
In many answer examples, the dp
table is created in 3D, but it is difficult to get an image in 3D and it was solved in 2D.
The goal of the dp
table to be created is to create the following table with the row subscript as the pasta type, the column subscript as the number of days, and the contents of the table as the number of cases ( In case of input example 2)
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 2 8 0 22 38 104 306 1120 0 1120 3360 0 3360 6720 16800 50400 134400 366240 1370880
2 0 1 2 8 0 22 38 104 410 0 1120 1120 0 3360 0 6720 20160 47040 134400 369600 1370880
3 0 1 2 6 16 0 44 120 404 0 0 1120 0 0 3360 6720 16800 50400 134400 366240 1370880
The process of creating this table is as follows. Since it is long, you can put it up to `` `j = 5```.
j=1----------
When added normally ↓
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
2 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
3 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
After erasing consecutive things ↓
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
2 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
3 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
j=2----------
When added normally ↓
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
2 0 1 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
3 0 1 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
After erasing consecutive things ↓
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
2 0 1 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
3 0 1 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
j=3----------
When added normally ↓
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 3 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
2 0 1 3 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
3 0 1 3 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
After erasing consecutive things ↓
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 2 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
2 0 1 2 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
3 0 1 2 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
j=4----------
When added normally ↓
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 2 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
2 0 1 2 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
3 0 1 2 8 24 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
After erasing consecutive things ↓
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 2 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
2 0 1 2 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
3 0 1 2 6 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
j=5----------
When added normally ↓
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 2 8 0 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
2 0 1 2 8 0 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
3 0 1 2 6 22 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
After erasing consecutive things ↓
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 2 8 0 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
2 0 1 2 8 0 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
3 0 1 2 6 16 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
dp
If you can create a table, the sum in the last column will be the answer.
D, N = map(int, input().split()) #D day, N kinds of clothes
T = [0] + [int(input()) for _ in range(D)] #Each day's temperature
clothes = [tuple(map(int, input().split())) for _ in range(N)] #(Lower limit temperature, upper limit temperature, flashiness)
dp = [[0] * (D+1) for _ in range(N)]
for j in range(2, D+1):
for i in range(N):
if T[j] < clothes[i][0] or clothes[i][1] < T[j]:
continue
score = 0
for k in range(N):
if T[j-1] < clothes[k][0] or clothes[k][1] < T[j-1]:
continue
score = max(score,
abs(clothes[i][2] - clothes[k][2]) + dp[k][j-1])
dp[i][j] = score
answer = 0
for i in range(N):
answer = max(answer, dp[i][-1])
print(answer)
The goal of this `` `dp``` table is to create the following table with the row subscript as clothes, the column subscript as the date, and the content as the absolute value of flashiness. (In the case of input example 1)
0 1 2 3
0 0 0 0 0
1 0 0 50 0
2 0 0 20 80
3 0 0 0 0
If you can create this table, the answer is the maximum value in the last column.
INF = float('inf')
N, M = map(int, input().split()) # N+1 city, need to carry within M days
D = [0] + [int(input()) for _ in range(N)] #City distance
C = [0] + [int(input()) for _ in range(M)] #Bad weather. Fatigue is C*D but 0 if not moving
MAX_break = M - N
# dp[i][j] :=Minimum fatigue to reach i by day j
dp = [[INF] * (M+1) for _ in range(N+1)]
for j in range(M+1):
dp[0][j] = 0
for i in range(1, N+1):
for j in range(1, M+1):
dp[i][j] = min(dp[i][j-1],
dp[i-1][j-1] + D[i] * C[j])
print(dp[-1][-1])
The goal of this `` `dp``` table is to create a table like the one below, with the row subscripts moved, the column subscripts as dates, and the contents as the minimum distance. (In the case of input example 1)
0 1 2 3 4 5
0 0.0 0.0 0.0 0.0 0.0 0.0
1 inf 500.0 300.0 150.0 150.0 150.0
2 inf inf 1250.0 675.0 675.0 675.0
3 inf inf inf 1475.0 1275.0 1125.0
If this table can be created, the answer is `dp [-1] [-1]
`.
import numpy as np
INF = float('inf')
N = int(input())
S = [[''] + list(input()) for _ in range(5)]
S_count = np.zeros((4, N+1))
for j in range(1, N+1):
for i in range(5):
if S[i][j] == 'R':
S_count[0, j] += 1
if S[i][j] == 'B':
S_count[1, j] += 1
if S[i][j] == 'W':
S_count[2, j] += 1
if S[i][j] == '#':
S_count[3, j] += 1
S_to_use = np.zeros((3, N+1))
for j in range(1, N+1):
for i in range(3):
S_to_use[i, j] = S_count[:, j].sum() - S_count[i, j]
dp = np.full((3, N+1), INF)
dp[:, 0] = 0
# dp[i, j] :=Minimum value when painting the jth column on i
for j in range(1, N+1):
for i in range(3):
for k in range(3):
if i == k:
continue
dp[i, j] = min(dp[i, j],
dp[k, j-1] + S_to_use[i, j])
answer = dp[:, -1].min()
print(int(answer))
In this `` `dp``` table, the subscript of the row is the color of the flag (R: 0, B: 1, W: 2), the subscript of the column is the column number, and the content is the smallest filled cell. As a number, the goal is to create a table like the one below. (In the case of input example 4)
0 1 2 3 4 5 6 7
0 0.0 4.0 6.0 12.0 13.0 15.0 18.0 23.0
1 0.0 3.0 8.0 11.0 11.0 17.0 19.0 21.0
2 0.0 4.0 7.0 8.0 15.0 15.0 20.0 21.0
The answer is the minimum value in the rightmost column of this table.
In this issue, we had to devise a pre-processing before creating the dp
table.
Specifically, `S_to_use`
in the answer code, which means, for example,
S_to_use [0, 2] `` `, which is necessary to paint the second column of the flag on R. Represents the number of squares.
If I could create this, I thought it wouldn't be that difficult to create a dp
table.
def cal(i):
return i * (i + 1) * (i + 2) // 6
def main(n):
proku = [0]
proku_odd = [0]
for i in range(1, 201):
num = cal(i)
proku.append(num)
if num % 2 != 0:
proku_odd.append(num)
dp = [0] * (n+1)
dp_odd = [0] * (n+1)
for j in range(n+1):
dp[j] = j
dp_odd[j] = j
for i in range(1, len(proku)):
for j in range(1, n+1):
if j-proku[i] < 0:
continue
if dp[j] > dp[j-proku[i]] + 1:
dp[j] = dp[j-proku[i]] + 1
for i in range(1, len(proku_odd)):
for j in range(1, n+1):
if j-proku_odd[i] < 0:
continue
if dp_odd[j] > dp_odd[j-proku_odd[i]] + 1:
dp_odd[j] = dp_odd[j-proku_odd[i]] + 1
print(dp[-1], dp_odd[-1])
if __name__ == "__main__":
while True:
n = int(input())
if n == 0:
break
main(n)
tle
I haven't fixed it, but I think it's probably this.
It's a little hard to understand the problem statement, but it's not that hard to do, it's just a normal `` dp```.
It can be solved in the same way as the knapsack problem (problem 36) that allows duplicates.
def main(N, M, C, X):
dp = [[INF] * 256 for _ in range(N+1)]
dp[0][128] = 0
for i in range(1, N+1):
for j in range(256):
for k in range(M):
next_j = j + C[k]
next_j = max(0, min(255, next_j))
dp[i][next_j] = min(dp[i][next_j],
dp[i-1][j] + pow(next_j - X[i-1], 2))
answer = min(dp[N][:])
return answer
if __name__ == "__main__":
INF = float('inf')
answer_list = []
while True:
N, M = map(int, input().split()) #N is the number of inputs, M is the number of numbers in the codebook
if N == M == 0:
break
C = [int(input()) for _ in range(M)] #Codebook
X = [int(input()) for _ in range(N)] #Input value
answer_list.append(main(N, M, C, X))
for answer in answer_list:
print(answer)
The problem is difficult to read. Again, the above code would be `` `TLE```. I think this is correct because all the answers are the same locally. It was a little difficult to speed up, so I will do it when I feel like it.
Recommended Posts