import java.util.Scanner;
import java.util.*;
//dp[i][j]表示从i个物品中选
//总体积不超过j的最大价值和

public class Main {
    static int N = 1010;
    static int n,V; //总数、总体积
    static int[] v = new int[N]; //表示体积
    static int[] w = new int[N];  //表示价值
    static int[][] dp = new int[N][N]; 

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);

        while (in.hasNextInt()) {
            n = in.nextInt();
            V = in.nextInt();
            //读入数据 ,从1开始读入,创建虚拟节点
            for(int i=1;i<=n;i++){
                v[i] = in.nextInt();
                w[i] = in.nextInt();
            }
           
           //1.解决第一问
           //1.初始化,虚拟节点初始化为0即可
           //2.填表
           for(int i =1;i<=n;i++){
            for(int j=1;j<=V;j++){
                //1.不选第i个物品的价值
                dp[i][j] = dp[i-1][j]; //价值与前一个相同
                //2.选第i个物品价值,需要判断j-v[i] 是否还能装得下,
                //取两种情况最大值
                if(j>=v[i]) dp[i][j] = Math.max(dp[i][j],dp[i-1][j-v[i]] +w[i]);
            }
           }
           System.out.println(dp[n][V]); //输出结果
           //解决第二问,先清空dp表
          for(int i=0;i<=n;i++){
            for(int j=0;j<=V;j++){
                dp[i][j] = 0;
                
            }
          }

           //1.初始化,上面的虚拟节点初始化为-1,因为不存在垓解
           for(int i=1;i<=V;i++) dp[0][i] = -1;

           //2.填表
            for(int i =1;i<=n;i++){
            for(int j=1;j<=V;j++){
                //1.不选第i个物品的价值
                dp[i][j] = dp[i-1][j]; //价值与前一个相同
                //2.选第i个物品价值,需要判断j-v[i] 是否还能装得下,
                //并且还要判断dp[i-1][j-v[i]] 是否有解
                if(j>=v[i] &&dp[i-1][j-v[i]] !=-1) dp[i][j] = Math.max(dp[i][j],dp[i-1][j-v[i]] +w[i]);
            }
           }
           //输出第二问的解,需要判断是否存在
           if(dp[n][V]==-1){
            System.out.println(0);
           }else{
            System.out.println(dp[n][V]); 
           }
          


            
        }
    }
}