#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int n,m;
vector<int> w(n),v(n);
for (int i=0;i<n;i++)
cin>>w[i]>>v[i];
//v为容量数组,W为价值数组,m为总容量
//优化的01揹包问题,使用一维数组进行存储。递推公式
//f[i][v] = max{f[i−1][v],f[i−1][v − c[i]]}
//变成 f[v]=max{f[v],f[v-c[i]]+w[i]}
//注意二层循环从后往前。
vector<int> f(m+1);
for (int i = 0; i < n; i++)
for (int j = m; j >= w[i]; j--){
f[j] = max(f[j], f[j - w[i]] + v[i]);
}
cout<<f[m]<<endl;
//未优化的01揹包问题,这里使用的是二维数组
//递推公式:f[i][v] = max{f[i−1][v],f[i−1][v − c[i]]}
//注意因为需要使用f[i-1]的值,因此二维数组一定是n+1*m+1的大小!!!
//此时为了方便,w,n数组尽量也需要n+1.
//如果w,v是给定的,建议使用上面的优化算法,或者记得循环时候i-1.
vector<int> w(n+1),v(n+1);
vector<vector<int>> f(n+1,vector<int>(m+1));
for (int i=1;i<=n;i++)
cin>>w[i]>>v[i];
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++){
if(j>=w[i]){
f[i][j] = max(f[i-1][j], f[i-1][j - w[i]] + v[i]);
}
else f[i][j] = f[i-1][j];
}
cout<<f[n][m]<<endl;
return 0;
}