#pragma GCC optimize("Ofast")  
#pragma GCC target("avx,avx2,fma") 
#pragma GCC optimization ("unroll-loops")
#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>  
#include <ext/pb_ds/tree_policy.hpp>   
using namespace std;
using namespace __gnu_pbds;

template <typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
 
template <typename T>
using ordered_multiset = tree<T, null_type, less_equal<T>, rb_tree_tag, tree_order_statistics_node_update>; 

#define pb push_back
#define fi first
#define se second
#define sz(x) ((long long int)x.size());
#define fr(i,a,b) for(int i=a; i<b; i++)
#define rfr(i,a,b) for(int i=a; i>b; i--)
#define trav(a,x) for(auto a:&x)
#define all(x) x.begin(),x.end()
#define fast ios_base::sync_with_stdio(false);cin.tie(NULL);
#define endl "\n"
#define max3(a,b,c) ((a>b)?(a>c)?a:c:(b>c)?b:c)
#define min3(a,b,c) ((a<b)?(a<c)?a:c:(b<c)?b:c)


typedef long long int ll;
typedef long double ld;
typedef vector<long long int> vi;
typedef vector<pair<long long int,long long int>> vii;
typedef map<long long int,long long int> mi;
typedef map<pair<long long int,long long int>, long long int> mii;
typedef pair<long long int, long long int> pii;

const ll inf=0x3f3f3f3f3f3f3f3fLL;
const ll mod=1000000007;
//const ll mod=998244353;

template<typename T>
void __p(T a) {
  cout<<a;
}
template<typename T, typename F>
void __p(pair<T, F> a) {
  cout<<"{";
  __p(a.first);
  cout<<",";
  __p(a.second);
  cout<<"}";
}
template<typename T>
void __p(std::vector<T> a) {
  cout<<"{";
  for(auto it=a.begin(); it<a.end(); it++)
    __p(*it),cout<<",}"[it+1==a.end()];
}
template<typename T, typename ...Arg>
void __p(T a1, Arg ...a) {
  __p(a1);
  __p(a...);
}

ll powm(ll a, ll b) {
	ll res=1;
	while(b) {
		if(b&1)
			res=(res*a)%mod;
		a=(a*a)%mod;
		b>>=1;
	}
	return res;
}

ll gcdExtended(ll,ll,ll *,ll *);
ll modInverse(ll a, ll m) 
{ 
		ll x, y; 
		ll g = gcdExtended(a, m, &x, &y); 
		g++;   //this line was added just to remove compiler warning
		ll res = (x%m + m) % m;
		return res;
} 
ll gcdExtended(ll a, ll b, ll *x, ll *y) 
{ 
		if (a == 0) 
		{ 
				*x = 0, *y = 1; 
				return b; 
		} 
		ll x1, y1; 
		ll gcd = gcdExtended(b%a, a, &x1, &y1);
		*x = y1 - (b/a) * x1; 
		*y = x1; 
		return gcd; 
}

ll add(ll a, ll b) {
	a += b;
	if (a >= mod) a -= mod;
	return a;
}
 
ll sub(ll a, ll b) {
	a -= b;
	if (a < 0) a += mod;
	return a;
}
 
ll mul(ll a, ll b) {
	return (a * b) % mod;
}

vector<int> sieveOfEratosthenes(int n) {
	vector<int> primes;
	bool prime[n + 1];
	memset(prime, true, sizeof(prime));
	for (int p = 2; p * p <= n; p++) {
		if (prime[p] == true) {
			for (int i = p * p; i <= n; i += p)
				prime[i] = false;
		}
	}
	for (int p = 2; p <= n; p++)
		if (prime[p])
			primes.push_back(p);
	return primes;
}

ll lcm(ll a,ll b){
    if(a==0 || b==0)
        return 0;
    return (a*b)/(__gcd(a,b));
}

//sort pair by second values
bool sortsec(const pair<ll,ll> &a, const pair<ll,ll> &b){ 
    return (a.second < b.second); 
}
//sort pair by first vals in descending
bool sortinrev(const pair<ll,ll> &a, const pair<ll,ll> &b){ 
    return (a.first > b.first); 
} 

bool isPrime(int n) 
{ 
    // Corner cases 
    if (n <= 1)  return false; 
    if (n <= 3)  return true; 
  
    // This is checked so that we can skip  
    // middle five numbers in below loop 
    if (n%2 == 0 || n%3 == 0) return false; 
  
    for (int i=5; i*i<=n; i=i+6) 
        if (n%i == 0 || n%(i+2) == 0) 
           return false; 
  
    return true; 
} 
ll dp[105][100005];

void solve(){
    ll n,w;
    cin>>n>>w;
    vii arr(n);
    ll x,y;
    fr(i,0,n){
        cin>>x>>y;
        arr[i]={x,y};
    }
    fr(i,1,n+1){
        fr(j,0,(w+1)){
            dp[i][j]=max(dp[i][j], dp[i-1][j]);
            if((j+arr[i-1].fi)<=w){
                dp[i][j+arr[i-1].fi]=max(dp[i][j+arr[i-1].fi], (dp[i-1][j]+arr[i-1].se));
            }
        }
    }
    ll ans=0;
    fr(i,0,100005){
        ans=max(ans,dp[n][i]);
    }
    cout<<ans<<endl;
}

int main(){
    fast
    int t=1;
    //cin>>t;              //Comment if NO multiple test-cases
    cout << fixed << setprecision(15);
    while(t--){
        solve();
    }
    return 0;
}

Measured memory_bytes: 81728