Read problems statements in [Hindi], [Mandarin Chinese], [Russian], [Vietnamese] and [Bengali] as well.

As everybody knows, Reza Shiri is the favourite Iranian artist. Since we love Reza Shiri and his songs, we never download them for free. Reza Shiri’s songs must be purchased from authorised stores. However, what if there is not enough money to buy all the songs?

There are $N$ songs (numbered $1$ through $N$) and $M$ albums (numbered $1$ through $M$) available. For each valid $i$, the $i$-th song has *greatness* $v_{i}$, price $p_{i}$ and belongs to the album $a_{i}$. For each valid $i$, the $i$-th album has price $b_{i}$. If we buy an album, then all songs from this album count as bought. It is also possible to buy any songs individually.

Your task is simple ― given the budget $P$ (the amount of money we have), calculate the maximum total greatness of songs we can buy. The total greatness is defined as the sum of greatness values of all distinct songs that are bought (either individually or as part of albums).

------  Input ------
The first line of the input contains three space-separated integers $N$, $M$ and $P$.
$N$ lines follow. For each $i$ ($1 ≤ i ≤ N$), the $i$-th of these lines contains three space-separated integers $a_{i}$, $p_{i}$ and $v_{i}$.
The last line contains $M$ space-separated integers $b_{1}, b_{2}, \ldots, b_{M}$.

------  Output ------
Print a single line containing one integer ― the maximum total greatness of songs we can afford to buy.

------  Constraints ------
$1 ≤ N, M, P ≤ 1,000$
$1 ≤ b_{i}, p_{i} ≤ P$ for each valid $i$
$1 ≤ v_{i} ≤ 10^{6}$ for each valid $i$
$1 ≤ a_{i} ≤ M$ for each valid $i$

----- Sample Input 1 ------ 
5 2 24

1 7 2

1 5 2

1 4 1

2 9 1

2 13 2

10 15
----- Sample Output 1 ------ 
7

Difficulty: VERY_HARD
Tags: Dynamic programming
Skill types: Dynamic programming

Starter code:

Solutions:
from collections import defaultdict
(n, m, b) = map(int, input().split())
d = defaultdict(list)
for i in range(n):
	(a, p, v) = map(int, input().split())
	d[a].append((p, v))
alb = list(map(int, input().split()))
dp = [[0 for x in range(b + 1)] for y in range(n + 1)]
s = 1
i = 1
while i <= m:
	j = 0
	sg = 0
	while j < len(d[i]):
		k = b
		ps = d[i][j][0]
		gs = d[i][j][1]
		sg += gs
		while k >= ps:
			dp[s][k] = max(dp[s - 1][k], dp[s - 1][k - ps] + gs)
			k -= 1
		k = 0
		while k < ps:
			dp[s][k] = dp[s - 1][k]
			k += 1
		j += 1
		s += 1
	k = b
	while k >= alb[i - 1]:
		dp[s - 1][k] = max(dp[s - 1 - j][k - alb[i - 1]] + sg, dp[s - 1][k])
		k -= 1
	i += 1
print(dp[n][b])


class node:

	def __init__(self):
		self.price = 0
		self.greatness = 0
		self.next = None

class node1:

	def __init__(self, val1, val2):
		self.price = val1
		self.greatness = val2
		self.next = None

def funn(n, m, p, l):
	list1 = [0] * (p + 1)
	list2 = [0] * (p + 1)
	for i in range(m):
		price = 0
		greatness = 0
		ref = l[i].next
		while ref != None:
			price = price + ref.price
			greatness = greatness + ref.greatness
			for j in range(p - ref.price, -1, -1):
				if ref.greatness + list1[j] > list1[ref.price + j]:
					list1[ref.price + j] = ref.greatness + list1[j]
			ref = ref.next
		l[i].greatness = greatness
		for j in range(p + 1):
			if j + l[i].price <= p and l[i].greatness + list2[j] > list1[l[i].price + j]:
				list1[l[i].price + j] = l[i].greatness + list2[j]
			if j + l[i].price >= p:
				break
		list2 = list1.copy()
	return list1[p]
s = input().split(' ')
N = int(s[0])
M = int(s[1])
P = int(s[2])
l = []
m = 0
while m < M:
	l.append(node())
	m += 1
n = 0
while n < N:
	s = input().split(' ')
	m = node1(int(s[1]), int(s[2]))
	m.next = l[int(s[0]) - 1].next
	l[int(s[0]) - 1].next = m
	n += 1
s = input().split(' ')
for i in range(M):
	l[i].price = int(s[i])
result = funn(N, M, P, l)
print(result)


(n, m, P) = map(int, input().split())
d = {}
for _ in range(n):
	(a, p, v) = map(int, input().split())
	if a in d:
		d[a].append([p, v])
	else:
		d[a] = [[p, v]]
x = sorted(d.items(), key=lambda y: y[0])
b = []
ap = list(map(int, input().split()))
for i in x:
	s = 0
	for j in i[1]:
		b.append([i[0], j[0], j[1], False])
		s += j[1]
	b.append([i[0], ap[i[0] - 1], s, True])
dp = [[0] * (P + 1) for _ in range(len(b) + 1)]
for i in range(1, len(b) + 1):
	(ano, p, v, album) = (b[i - 1][0], b[i - 1][1], b[i - 1][2], b[i - 1][3])
	for j in range(1, P + 1):
		if not album:
			if j >= p:
				dp[i][j] = max(v + dp[i - 1][j - p], dp[i - 1][j])
			else:
				dp[i][j] = dp[i - 1][j]
		elif j >= p:
			dp[i][j] = max(v + dp[i - len(d[ano]) - 1][j - p], dp[i - 1][j])
		else:
			dp[i][j] = dp[i - 1][j]
print(dp[-1][-1])


(n, m, P) = map(int, input().split())
d = []
for i in range(n):
	(a, p, v) = tuple(map(int, input().split()))
	d.append((a - 1, p, v))
b = list(map(int, input().split()))
d.sort()
prev = [-1] * m
album_v = [0] * m
for i in range(n):
	album_v[d[i][0]] += d[i][2]
	if i + 1 < n and d[i][0] != d[i + 1][0]:
		prev[d[i + 1][0]] = i
dp = []
for _ in range(P + 1):
	dp.append([])
	for _ in range(n):
		dp[-1].append(0)
ans = 0
for i in range(n):
	(album, price, value) = d[i]
	album_price = b[album]
	album_value = album_v[album]
	prev_i = prev[album]
	for budget in range(1, P + 1):
		res = dp[budget][i - 1] if i - 1 >= 0 else 0
		if budget >= price:
			res = max(res, (dp[budget - price][i - 1] if i - 1 >= 0 else 0) + value)
		if budget >= album_price and (i == n - 1 or d[i + 1][0] != album):
			res = max(res, (dp[budget - album_price][prev_i] if prev_i >= 0 else 0) + album_value)
		dp[budget][i] = res
		ans = max(ans, res)
print(ans)