import numpy as np



N, W = list(map(int, input().split()))



dp = np.zeros(W+1, dtype=np.int64)



for _ in range(N):

    w, v = list(map(int, input().split()))

    np.maximum(dp[:-w]+v, dp[w:], out=dp[w:])



print((dp[-1]))

import numpy as np



N, W = list(map(int, input().split()))



dp = np.zeros(W+1, dtype=np.int64)



for _ in range(N):

    w, v = list(map(int, input().split()))  # 重さw, 価値vの荷物

    np.maximum(dp[:-w]+v, dp[w:], out=dp[w:])  # dp[:-w]はまだ重さwのもの入るナップサックの状態

    # outは戻り値を格納する配列を指定できる



print((dp[-1]))





"""

今dpは一次元配列

dp[:-w]は後ろからw個より前の要素, つまり(N-w)個

dp[w:]は前からw個より後ろの要素, つまり(N-w)個

よって形状が一致する

"""



"""

dp[:-w]は今見ている"重さw, 価値v"の荷物を入れることのできる状態のナップサック

dp[:-w]+vをすることで、今見ているその荷物を入れた時の価値の総和になる.

今、"重さw, 価値v"の荷物を入れたナップサックと、dp[w:]を比較する。

それぞれの要素について大きい方が新しい要素となり、out=dp[w:]によって上書きされる。

maxmimumが返すのはnp配列。そのnp配列の形状は比較対象となっている配列の形状と一致するから、

問題なく上書きできる

"""

import numpy as np

N, W = list(map(int, input().split()))
dp = np.zeros(W + 1, dtype=np.int64)
for _ in range(N):
    w, v = list(map(int, input().split()))
    np.maximum(dp[:-w] + v, dp[w:], out=dp[w:])
print((dp[-1]))

import numpy as np

N, W = list(map(int, input().split()))
dp = np.zeros(W + 1, dtype=np.int64)
for _ in range(N):
    w, v = list(map(int, input().split()))  # 重さw, 価値vの荷物
    np.maximum(dp[:-w] + v, dp[w:], out=dp[w:])  # dp[:-w]はまだ重さwのもの入るナップサックの状態
    # outは戻り値を格納する配列を指定できる
print((dp[-1]))
"""
今dpは一次元配列
dp[:-w]は後ろからw個より前の要素, つまり(N-w)個
dp[w:]は前からw個より後ろの要素, つまり(N-w)個
よって形状が一致する
"""
"""
dp[:-w]は今見ている"重さw, 価値v"の荷物を入れることのできる状態のナップサック
dp[:-w]+vをすることで、今見ているその荷物を入れた時の価値の総和になる.
今、"重さw, 価値v"の荷物を入れたナップサックと、dp[w:]を比較する。
それぞれの要素について大きい方が新しい要素となり、out=dp[w:]によって上書きされる。
maxmimumが返すのはnp配列。そのnp配列の形状は比較対象となっている配列の形状と一致するから、
問題なく上書きできる
"""

-    w, v = list(map(int, input().split())) -    np.maximum(dp[:-w] + v, dp[w:], out=dp[w:]) +    w, v = list(map(int, input().split()))  # 重さw, 価値vの荷物 +    np.maximum(dp[:-w] + v, dp[w:], out=dp[w:])  # dp[:-w]はまだ重さwのもの入るナップサックの状態 +    # outは戻り値を格納する配列を指定できる +""" +今dpは一次元配列 +dp[:-w]は後ろからw個より前の要素, つまり(N-w)個 +dp[w:]は前からw個より後ろの要素, つまり(N-w)個 +よって形状が一致する +""" +""" +dp[:-w]は今見ている"重さw, 価値v"の荷物を入れることのできる状態のナップサック +dp[:-w]+vをすることで、今見ているその荷物を入れた時の価値の総和になる. +今、"重さw, 価値v"の荷物を入れたナップサックと、dp[w:]を比較する。 +それぞれの要素について大きい方が新しい要素となり、out=dp[w:]によって上書きされる。 +maxmimumが返すのはnp配列。そのnp配列の形状は比較対象となっている配列の形状と一致するから、 +問題なく上書きできる +"""