#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int> pi;
typedef vector<int> vi;
typedef vector<string> vs;
typedef vector<pi> vpi;
typedef vector<vi> vii;
typedef map<int, int> mp;
typedef set<int> set;
typedef multiset<int> mset;
typedef long int int32;
typedef unsigned long int uint32;
typedef long long int int64;
typedef unsigned long long int  uint64;
typedef vector<int64> vi64;
#define fast ios_base::sync_with_stdio(0);cin.tie(NULL);cout.tie(NULL)
#define form(i,j,k,l) for(int i=j;i<int(k);i+=l)
#define rform(i,j,k,l) for(int i=int(j);i>int(l);i-=l)
#define rep(i, j) for(int i=0;i<int(j);i++)
#define rrep(i, j) for(int i=int(j);i>=0;i--)
#define all(cont) cont.begin(), cont.end()
#define rall(cont) cont.end(), cont.begin()
#define forc(it, l) for (auto it = l.begin(); it != l.end(); it++)
#define IN(A, B, C) assert( B <= A && A <= C)
#define mp(x,y) make_pair(x,y)
#define pb(x) push_back(x)
#define INF (int)1e9
#define EPS 1e-9
#define PI 3.1415926535897932384626433832795
#define MOD 1000000009
#define read(type) readInt<type>()
#define F first
#define S  second
const double pie = acos(-1.0);
template <typename T>
T Max(T x, T y)
{
	return (x > y) ? x : y;
}
template <typename T>
T Min(T x, T y)
{
	return (x > y) ? y : x;
}

int gcd(int n1, int n2)
{
	if (n2 != 0) return gcd(n2, n1 % n2);
	else return n1;
}
/*
#define TRACE

#ifdef TRACE
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1) {
	cerr << name << " : " << arg1 << std::endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args) {
	const char* comma = strchr(names + 1, ','); cerr.write(names, comma - names) << " : " << arg1 << " | "; __f(comma + 1, args...);
}
#else
#define trace(...)
#endif
clock_t time_p = clock();
void rtime() { time_p = clock() - time_p; cerr << "Time Taken : " << (float)1000 * (time_p) / CLOCKS_PER_SEC << "\n";}
int sudoku[10][10];
bool check_sudoku(int sudoku[10][10], int n, int i, int j)
{
	form(r1, 1, 10, 1)
	{	if (sudoku[r1][j] == n)
			return false;
	}
	form(r1, 1, 10, 1)
	{	if (sudoku[i][r1] == n)
			return false;
	}
	int r1, r2, c1, c2;
	if (i <= 3)
		r1 = 1, r2 = 3;
	else if (i > 3 && i <= 6)
		r1 = 4, r2 = 6;
	else
		r1 = 7, r2 = 9;

	if (j <= 3)
		c1 = 1, c2 = 3;
	else if (j > 3 && j <= 6)
		c1 = 4, c2 = 6;
	else
		c1 = 7, c2 = 9;
	form(k, r1, r2 + 1, 1)
	{	form(l, c1, c2 + 1, 1)
		{	if (sudoku[k][l] == n)
				return false;

		}

	}
	return true;
}

bool  solu(int sudoku[10][10], int  i, int  j, int n, int m)
{
	if (i == n && j == m)
	{	form(x, 1, 10, 1)
		{	form(y, 1, 10, 1)
			cout << sudoku[x][y] << " ";
			cout << endl;
		}
		return true;
	}
	i = 0;
	j = 0;
	form(x, 1, 10, 1)
	{	form(y, 1, 10, 1)
		{
			if (sudoku[x][y] == 0)
			{
				i = x;
				j = y;
				break;
			}
		}
		if (i != 0)
			break;
	}

	form(l, 1, 10, 1)
	{	if (check_sudoku(sudoku, l, i, j))
		{	sudoku[i][j] = l;
			if (solu(sudoku, i, j, n, m))
				return true;

			sudoku[i][j] = 0;//backtracking
		}
	}
	return false;
}
*/
int main()
{	fast;
/*
#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
*/	int n, m;
	cin >> n >> m;
	pair<long long int , long long int> arr[n];
	for (int i = 0; i < n; i++)
		cin >> arr[i].first >> arr[i].second;
	sort(arr, arr + n);
	long long int dp[n + 1][m + 1];
	for (int i = 0; i < n + 1; i++)
	{	for (int j = 0; j < m + 1; j++)
		{	if (i == 0 || j == 0)
				dp[i][j] = 0;

			else
			{	if (arr[i - 1].first > j)
					dp[i][j] = dp[i - 1][j];
				else
					dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - arr[i - 1].first] + arr[i - 1].second);
			}
		}
	}
	long long int max = 0;
	for (int i = 0; i < n + 1; i++)
	{	if (dp[i][m] >= max)
			max = dp[i][m];
	}
	cout << max;
}


Measured memory_bytes: 79104