#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
#include <vector>
#include <set>
#include <map>
#include <unordered_map>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cstdlib>
#include <algorithm>
#include <list>
#include <string>
#include <cmath>
#include <bitset>
#include <stack>
#include <unordered_set>
#define ull unsigned long long
#define ll long long
#define pii pair<ll ,ll>
#define ft first
#define sd second
#define pr pair
#define cy cout<<"Yes"<<endl
#define cn cout<<"No"<<endl
#define forn(i,n) for(int (i)=0;(i)<(n);(i)++)
#define forne(i,n) for(int (i)=1;(i)<=(n);(i)++)
#define rforn(i,n) for(int (i)=(n-1);(i)>=(0);(i)--)
#define rforne(i,n) for(int (i)=(n);(i)>=(1);(i)--)
#define vv vector
const int inf = 0x004f4f4f;
const int N = 1e6 + 10;
const int MAXN = 1e5 + 8;
void solve() {
int n, W; cin >> n >> W;
vector<ll>v(n), w(n), m(n);
vector<pii>thing;
forn(i, n) {
cin >> v[i] >> w[i] >> m[i];
}
forn(i, n) {
auto ret = m[i];
ll k = 1;
while (ret) {
if (ret & 1) {
thing.push_back({ v[i]*k,w[i]*k });
}
k *= 2;
ret >>= 1;
}
}
vector<ll>f(W+1);
forn(i, thing.size()) {
rforne(j, W) {
if (j < thing[i].second)
continue;
else
f[j] = max(f[j - thing[i].second] + thing[i].first, f[j]);
}
}
cout << f[W] << endl;
}
int main() {
int t;
t = 1;
while (t--)
solve();
return 0;
}