def solve():

    from collections import namedtuple

    import sys



    input = sys.stdin.readline

    Dish = namedtuple('Dish', 'idx cost pt')



    n, t = list(map(int, input().split()))

    dishes = []

    for idx in range(1, n + 1):

        cost, pt = list(map(int, input().split()))

        dishes.append(Dish(idx=idx, cost=cost, pt=pt))



    dp = [[0] * 2 for _ in range(t)]

    # dp[完食にかかる総時間][最後の皿を選んだか]:= 美味しさの最大値



    for dish in dishes:

        for cost_ in range(t - 1, -1, -1):

            dp[cost_][True] = max(dp[cost_][True], dp[cost_][False] + dish.pt)

            if cost_ >= dish.cost:

                dp[cost_][False] = max(dp[cost_][False], dp[cost_ - dish.cost][False] + dish.pt)

                dp[cost_][True] = max(dp[cost_][True], dp[cost_ - dish.cost][True] + dish.pt)



    return max(dp[cost_][True] for cost_ in range(t))





print((solve()))



# 最後の皿を選んだかフラグを設ける

# https://sen-comp.hatenablog.com/entry/2019/11/17/003150

def solve():

    from collections import namedtuple

    from operator import attrgetter

    import sys



    input = sys.stdin.readline

    Dish = namedtuple('Dish', 'idx cost pt')



    n, t = list(map(int, input().split()))

    dishes = []

    for idx in range(1, n + 1):

        cost, pt = list(map(int, input().split()))

        dishes.append(Dish(idx=idx, cost=cost, pt=pt))



    dishes.sort(key=attrgetter('cost'))



    dp = [0] * t

    # dp[完食にかかる総時間]:= 美味しさの最大値



    ret = 0

    for dish in dishes:

        for cost_ in range(t - 1, -1, -1):

            ret = max(ret, dp[cost_] + dish.pt)

            if cost_ >= dish.cost:

                dp[cost_] = max(dp[cost_], dp[cost_ - dish.cost] + dish.pt)



    return ret





print((solve()))



# コスト昇順ソートした皿で、DPする

# 各皿は最後の皿（コスト0で、ポイントだけ加算し、以降は皿を取れない）にすることができる

# 最後の皿を選んだ時点でのポイントのmax

# https://sen-comp.hatenablog.com/entry/2019/11/17/003150

def solve():
    from collections import namedtuple
    import sys

    input = sys.stdin.readline
    Dish = namedtuple("Dish", "idx cost pt")
    n, t = list(map(int, input().split()))
    dishes = []
    for idx in range(1, n + 1):
        cost, pt = list(map(int, input().split()))
        dishes.append(Dish(idx=idx, cost=cost, pt=pt))
    dp = [[0] * 2 for _ in range(t)]
    # dp[完食にかかる総時間][最後の皿を選んだか]:= 美味しさの最大値
    for dish in dishes:
        for cost_ in range(t - 1, -1, -1):
            dp[cost_][True] = max(dp[cost_][True], dp[cost_][False] + dish.pt)
            if cost_ >= dish.cost:
                dp[cost_][False] = max(
                    dp[cost_][False], dp[cost_ - dish.cost][False] + dish.pt
                )
                dp[cost_][True] = max(
                    dp[cost_][True], dp[cost_ - dish.cost][True] + dish.pt
                )
    return max(dp[cost_][True] for cost_ in range(t))


print((solve()))
# 最後の皿を選んだかフラグを設ける
# https://sen-comp.hatenablog.com/entry/2019/11/17/003150

def solve():
    from collections import namedtuple
    from operator import attrgetter
    import sys

    input = sys.stdin.readline
    Dish = namedtuple("Dish", "idx cost pt")
    n, t = list(map(int, input().split()))
    dishes = []
    for idx in range(1, n + 1):
        cost, pt = list(map(int, input().split()))
        dishes.append(Dish(idx=idx, cost=cost, pt=pt))
    dishes.sort(key=attrgetter("cost"))
    dp = [0] * t
    # dp[完食にかかる総時間]:= 美味しさの最大値
    ret = 0
    for dish in dishes:
        for cost_ in range(t - 1, -1, -1):
            ret = max(ret, dp[cost_] + dish.pt)
            if cost_ >= dish.cost:
                dp[cost_] = max(dp[cost_], dp[cost_ - dish.cost] + dish.pt)
    return ret


print((solve()))
# コスト昇順ソートした皿で、DPする
# 各皿は最後の皿（コスト0で、ポイントだけ加算し、以降は皿を取れない）にすることができる
# 最後の皿を選んだ時点でのポイントのmax
# https://sen-comp.hatenablog.com/entry/2019/11/17/003150

+    from operator import attrgetter -    dp = [[0] * 2 for _ in range(t)] -    # dp[完食にかかる総時間][最後の皿を選んだか]:= 美味しさの最大値 +    dishes.sort(key=attrgetter("cost")) +    dp = [0] * t +    # dp[完食にかかる総時間]:= 美味しさの最大値 +    ret = 0 -            dp[cost_][True] = max(dp[cost_][True], dp[cost_][False] + dish.pt) +            ret = max(ret, dp[cost_] + dish.pt) -                dp[cost_][False] = max( -                    dp[cost_][False], dp[cost_ - dish.cost][False] + dish.pt -                ) -                dp[cost_][True] = max( -                    dp[cost_][True], dp[cost_ - dish.cost][True] + dish.pt -                ) -    return max(dp[cost_][True] for cost_ in range(t)) +                dp[cost_] = max(dp[cost_], dp[cost_ - dish.cost] + dish.pt) +    return ret -# 最後の皿を選んだかフラグを設ける +# コスト昇順ソートした皿で、DPする +# 各皿は最後の皿（コスト0で、ポイントだけ加算し、以降は皿を取れない）にすることができる +# 最後の皿を選んだ時点でのポイントのmax