#include <cmath>
#include <cstdio>
#include <vector>
#include <math.h>
#include <iostream>
#include <fstream>
#include <algorithm>
#include <iomanip>
using namespace std;
ifstream f("rucsac.in");
ofstream g("rucsac.out");
int v[5009];
int main()
{
long long int n, G, Wi, Pi;
f >> n >> G;
for (; n>0; n--)
{
f >> Wi >> Pi;
for (int i = G - Wi; i >= 0; i--)
if (v[Wi + i]<v[i] + Pi)
v[Wi + i] = v[i] + Pi;
}
g << v[G];
return 0;
}
/*struct Point
{
int x;
int y;
};
bool onSegment(Point p, Point q, Point r)
{
if (q.x <= max(p.x, r.x) && q.x >= min(p.x, r.x) &&
q.y <= max(p.y, r.y) && q.y >= min(p.y, r.y))
return true;
return false;
}
int orientation(Point p, Point q, Point r)
{
int val = (q.y - p.y) * (r.x - q.x) -
(q.x - p.x) * (r.y - q.y);
if (val == 0) return 0; // colinear
return (val > 0) ? 1 : 2; // clock or counterclock wise
}
bool doIntersect(Point p1, Point q1, Point p2, Point q2)
{
int o1 = orientation(p1, q1, p2);
int o2 = orientation(p1, q1, q2);
int o3 = orientation(p2, q2, p1);
int o4 = orientation(p2, q2, q1);
if (o1 != o2 && o3 != o4)
return true;
if (o1 == 0 && onSegment(p1, p2, q1)) return true;
if (o2 == 0 && onSegment(p1, q2, q1)) return true;
if (o3 == 0 && onSegment(p2, p1, q2)) return true;
if (o4 == 0 && onSegment(p2, q1, q2)) return true;
return false;
}
struct tinta {
int x, y1, y2;
};
struct pos {
int x, y, r;
};
int main()
{
int tr, ti;
ifstream f("arcas.in");
ofstream gout("arcas.out");
f >> ti >> tr;
tinta *tinte = new tinta[ti];
pos *pozitii = new pos[ti];
loop(ti)
{
f >> tinte[i].x >> tinte[i].y1 >> tinte[i].y2;
}
loop(tr)
{
f >> pozitii[i].x >> pozitii[i].y >> pozitii[i].r;
}
loop(tr)
{
int counter = 0;
int e = pozitii[i].x, f = pozitii[i].y, g = pozitii[i].x+pozitii[i].r, h = pozitii[i].y+pozitii[i].r;
struct Point p2 = { e, f }, q2 = { g, h };
for (int j = 0; j < ti; j++)
{
int a = tinte[j].x, b = tinte[j].y1, c = tinte[j].x, d = tinte[j].y2;
struct Point p1 = { a, b }, q1 = { c, c };
if (doIntersect(p1, q1, p2, q2))
{
counter++;
}
}
gout << counter << endl;
}
}*/