#include<iostream>
#include<cstdio>
using namespace std;
#define MAX(a,b) (a>b)?a:b
const int SIZE=1000+16;
int nKind; //物品种类数目
int nLimit; //背包容量
int val[SIZE]; //每种背包的价值
int weight[SIZE]; //每种背包的重量
int bag[SIZE]; //每种背包的数目
int dp[SIZE];
//0-1背包, 代价为cost, 获得的价值为value
void ZeroOnePack(int cost, int value)
{
for(int i=nLimit; i>=cost; i--) //逆序
{
dp[i]=MAX(dp[i], dp[i-cost]+value);
}
}
//完全背包, 代价为cost, 获得的价值为value
void CompletePack(int cost, int value)
{
for(int i=cost; i<=nLimit; i++) //顺序
{
dp[i]=MAX(dp[i],dp[i-cost]+value);
}
}
//多重背包 代价为cost, 获得的价值为value, 该种背包的数目为amount
void MultiplePack(int cost, int value, int amount)
{
if(cost*amount>=nLimit) CompletePack(cost, value);
else
{
int k=1;
while(k<amount)
{
ZeroOnePack(k*cost, k*value);
amount-=k;
k<<=1;
}
ZeroOnePack(amount*cost, amount*value);
}
}
int main()
{
//不要求装满则dp中的元素均为零;
//否则dp[0]=0.其他为 -INF
memset(dp,0,sizeof(dp));
scanf("%d %d",&nKind,&nLimit);
for(int i=0;i<nKind;i++)
{
scanf("%d %d %d",&weight[i],&val[i],&bag[i]);
}
for(int i=0; i<nKind; i++)
MultiplePack(weight[i],val[i],bag[i]);
printf("%d\n",dp[nLimit]);
return 0;
}