#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
struct poj3624 {
/* 【问题描述】:典型的01背包问题,
* 给定n个物品,每个物品i有重量w[i]和价值d[i],背包容量为M,
* 要求在不超过背包容量的前提下,使背包中物品的价值最大(每个物品只能出现一次)
*/
/* 【解题思路】:f[n,v]表示只考虑前n个物品且恰好装满空间为v的背包所得到的最大价值,
* 则f[n,v]=max{f[n-1,v],f[n-1][v-w[n]]+d[n]}
* 边界条件:f[0,x]=0
* 由于每次决策只跟“上一层”的相关,可以采用一维数组来保存“上一层”的决策
*/
int n, M;
int w[3500], d[3500];
int f[13000];
void work() {
while (cin >> n >> M) {
for (int i = 1; i <= n; i++)
cin >> w[i] >> d[i];
memset(f, 0, sizeof(f));
for (int i = 1; i <= n; i++) {
for (int j = M; j >= w[i]; j--) {
f[j] = max(f[j], f[j - w[i]] + d[i]);
}
}
int ans = 0;
for (int i = 0; i <= M; i++)
ans = max(ans, f[i]);
cout << ans << endl;
}
}
};
int main()
{
poj3624 solution;
solution.work();
return 0;
}