// 2. 01背包问题
// 有 N 件物品和一个容量是 V 的背包。每件物品只能使用一次。
// 第 i 件物品的体积是 vi,价值是 wi。
// 求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
// 输出最大价值。
// 输入格式
// 第一行两个整数,N,V,用空格隔开,分别表示物品数量和背包容积。
// 接下来有 N 行,每行两个整数 vi,wi,用空格隔开,分别表示第 i 件物品的体积和价值。
// 输出格式
// 输出一个整数,表示最大价值。
// 数据范围
// 0<N,V≤1000
// 0<vi,wi≤1000
// 输入样例
// 4 5
// 1 2
// 2 4
// 3 4
// 4 5
// 输出样例:
// 8
#include<bits/stdc++.h>
using namespace std;
const int N =1050;
// int dp[N][N];
int w[N],v[N];
int f[N];
int main(void){
int n, m;
cin >> n >> m;
for(int i=1; i<=n; i++){
cin >> v[i]>>w[i];
}
for (int i = 1; i <=n; i++)
{
for (int j = m; j >=v[i]; j--)
{
/* code */
//>=v[i]就不用判断是否满足
f[j] = max(f[j], f[j-v[i]] + w[i]);
//f[j]要用f[j-v[i]],如果正序计算,那么原来的f[j-v[i]]就已经被修改过了
//错误,所以要逆序
//
// 容量 1 2 3 4 5
// 第i件物品 v[i]体积 w[i]价值 选择情况
// i=1 1 2 2 2 2 2 2
// i=2 *2* 4 2 *4* 6 *6* 6
// i=3 3 4 2 4 6 6 8
// i=4 4 5 2 4 6 6 8
// f[j]代表j容量下的最大价值
// 外面的i循环还是代表第i件物品
// j代表的是j容量
// v[2] = 2 w[2]= 4
// 如果j=4,i =2 f[4] = max(f[4-v[2]]+w[2], f[4])
// f[j-v[i]]的意思是体积为j-v[i]时的最大价值
// 倒序情况:
// f[4-v[2]]+ w[2]= f[2]+4 = 6
// 这里的f[2]第i-1层的f2,
// 正序情况
// 这里的f[2]是第i层的f2,因为正序的话原来第i-1层的f2已经被更新了
// 现在f[4-v[2]]+w[2] = f[2] +4 = 4+4 = 8
}
/* code */
}
cout<<f[m];
system("pause");
}
// int main(void){
// int n, m;
// cin >> n >> m;
// //n件物品,容量为v的背包
// //第i件物品体积是vi, 重量是wi
// // dp[0][0-m,]都初始化为0,代表的是前i个物品,背包容量为j下的最大值
// for(int i=1; i<=n; i++){
// cin >> v[i] >> w[i];
// }
// // cout<<"物品数量"<<" "<<"容量 "<<"所选物品"<<endl;
// for(int i=1; i<=n; i++){
// cout<<" 物品数量"<<i<<" "<<endl;
// for(int j=1; j<=m; j++){
// cout<<"容量"<<j<<" ";
// if(j<v[i]){
// dp[i][j] = dp[i-1][j];
// cout<<"保持了第"<<i-1<<"种物品时的情况 ";
// }
// else{
// dp[i][j] = max(dp[i-1][j],dp[i-1][j-v[i]]+w[i]);
// //选了
// cout<<"在"<<i-1<<"个物品的基础上选择了不超过"<<j-v[i]<<"的体积"<<endl;
// cout<<"加入了"<<v[i]<<endl;
// }
// cout<<"价值为"<<dp[i][j]<<endl;
// cout<<endl;
// }
// }
// system("pause");
// }