#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxm = 12880 + 5;
const int maxn = 3402 + 5;
int F[maxn][maxm]; //F[i][j]表示前j个物品重量为i的的最大权重 看样子要使用滚动数组
int N, M;
struct node{
int w, d;
}s[maxn];
void pre() {
memset(F, 0, sizeof(F));
for(int i = 1; i <= N; i++)
for(int j = 1; j <= M; j++){
if(j >= s[i].w) { //这个条件非常重要 要仔细点儿
F[i][j] = max((F[i-1][j-s[i].w]+s[i].d), F[i-1][j]);
}
else
F[i][j] = F[i-1][j];
}
}
int main() {
cin >> N >> M;
for(int i = 1; i <= N; i++) {
cin >> s[i].w >> s[i].d;
}
pre();
cout << F[N][M] << endl;
return 0;
}
//======使用滚动数组=============//
#include<iostream>
#include<cstring>
using namespace std;
const int maxm = 12880 + 5;
const int maxn = 3402 + 5;
int F[maxm]; //F[i][j]表示前j个物品重量为i的的最大权重 看样子要使用滚动数组
int N, M;
struct node{
int w, d;
}s[maxn];
void pre() {
memset(F, 0, sizeof(F));
for(int i = 1; i <= N; i++)
for(int j = M; j >= 1; j--){
if(j >= s[i].w) { //这个条件非常重要 要仔细点儿
F[j] = max((F[j-s[i].w]+s[i].d), F[j]);
}
}
}
int main() {
cin >> N >> M;
for(int i = 1; i <= N; i++) {
cin >> s[i].w >> s[i].d;
}
pre();
cout << F[M] << endl;
return 0;
}
//======使用滚动数组 + 优化输入 + 优化空间=============//
#include<iostream>
#include<cstring>
using namespace std;
const int maxm = 12880 + 5;
const int maxn = 3402 + 5;
int F[maxm];
int N, M;
struct node{
int w, d;
}s;
int main() {
cin >> N >> M;
memset(F, 0, sizeof(F));
for(int i = 1; i <= N; i++) {
cin >> s.w >> s.d;
for(int j = M; j >= 1; j--){
if(j >= s.w) { //这个条件非常重要 要仔细点儿
F[j] = max((F[j-s.w]+s.d), F[j]);
}
}
}
cout << F[M] << endl;
return 0;
}