#include <bits/stdc++.h>
#define _GLIBCXX_DEBUG
using namespace std;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define Sort(a) sort(a.begin(), a.end())
#define Reve(a) reverse(a.begin(), a.end())
#define PI 3.14159265359
typedef long long ll;
const ll MOD = 1e9+7;

ll gcd(ll a, ll b){
  if(b==0) return a;
  return gcd(b, a%b);
}
/*ll myPow(ll x, ll n, ll m){
  if(n == 0)
    return 1;
  if(n % 2 == 0)
    return myPow(x * x % m, n / 2, m);
  else
    return x * myPow(x, n - 1, m) % m;
}*/

ll lcm(ll a, ll b){
  ll g = gcd(a, b);
  b /= g;
  a *= b;
  return a;
}

//素数判定 O(√n)
bool is_prime(int64_t n){
  for(int64_t i = 2; i*i<=n; i++){
    if(n%i==0) return false;
  }
  return n!=1;
}

//約数の列挙 O(√n)
vector<int64_t> dividor(int64_t n){
  vector<int64_t> res;
  for(int64_t i=1; i*i<=n; i++){
    if(n%i==0){
      res.push_back(i);
      if(i != n/i) res.push_back(i);
    }
  }
  return res;
}

//素因数分解 O(√n)
map<int64_t, int64_t> prime_factor(int64_t n){
  map<int64_t, int64_t> res;
  for(int64_t i=2; i*i<=n; i++){
    while(n%i==0){
      res[i]++;
      n /= i;
    }
  }
  if(n != 1) res[n] = 1;
  return res;
}
struct UnionFind {
    vector<int> par; // par[i]:iの親の番号　(例) par[3] = 2 : 3の親が2

    UnionFind(int N) : par(N) { //最初は全てが根であるとして初期化
        for(int i = 0; i < N; i++) par[i] = i;
    }

    int root(int x) { // データxが属する木の根を再帰で得る：root(x) = {xの木の根}
        if (par[x] == x) return x;
        return par[x] = root(par[x]);
    }

    void unite(int x, int y) { // xとyの木を併合
        int rx = root(x); //xの根をrx
        int ry = root(y); //yの根をry
        if (rx == ry) return; //xとyの根が同じ(=同じ木にある)時はそのまま
        par[rx] = ry; //xとyの根が同じでない(=同じ木にない)時：xの根rxをyの根ryにつける
    }

    bool same(int x, int y) { // 2つのデータx, yが属する木が同じならtrueを返す
        int rx = root(x);
        int ry = root(y);
        return rx == ry;
    }
};

  


/*int main(){ 
  int64_t n, k; cin >> n >> k;
  vector<int64_t> A(n);
  int64_t a;
  rep(i, n){
    cin >> a;
    A[i] = a-1;
  }
  int64_t p=A[0];
  int64_t c;
  int64_t ct2=0LL;
  map<int64_t, int64_t> B;
  //cout << 1 << endl;
  rep(i, n){
    if(B.count(p)){
      c = p;
      break;
    }
    else {
      B[p] = A[p];
      p = A[p];
      ct2++;
    }
  }
  //cout << p <<
  //cout << 1 << endl;
  p=A[0];
  int64_t ct1=0LL; 
  rep(i, n){
    if(p==c){
      break;
    }
    else {
      ct1++;
      p = A[p];
    }
  }
  //cout << ct2 << endl;
  k -= ct1;
  //cout << ct1 << endl;
  int64_t ct = ct2-ct1;
  //cout << ct << endl;
  int64_t r;
  r = k%ct;
  //cout << 1 << endl;
  r--;
  //cout << 1 << endl;
  if(r<0) {r = ct-1;}
  p = c;
  rep(i, r){
    p=B[p];
  }
  cout << p+1 << endl;
}*/

int main(){
  int n, m, x;
  cin >> n >> m >> x;
  vector<vector<int>> D(n, vector<int>(m));
  vector<int> C(n);
  vector<int> B(m);
  rep(i, n){
    cin >> C[i];
    rep(j, m){
      cin >> D[i][j];
    }
  }
  int ans = 1000000000;
    for (int tmp = 0; tmp < (1 << 12); tmp++) {
    bitset<12> s(tmp);  // 最大20個なので20ビットのビット列として扱う
 
    // ビット列の1のビットに対応する整数を選んだとみなして総和を求める
    /*int sum = 0;
    for (int i = 0; i < N; i++) {
      if (s.test(i)) {
        sum += A.at(i);
      }
    }*/
    /*if (sum == K) {
      ans = true;
    }*/
    
    int c;
    c = 0;
    rep(i, n){
      if(s.test(i)){
        rep(j, m){
          B[j] += D[i][j];
        }
        c += C[i];
      }
    }
    int ch = 0;
    rep(i, m){
      if(B[i]<x) {ch=1; break;}     
    }
    rep(i, m) B[i]=0;
    if(ch==0) ans = min(ans, c);

  }
  if(ans==1000000000) cout << -1 << endl;
  else cout << ans << endl;
}

Measured memory_bytes: 3636