use std::vec::Vec;

fn read<T: std::str::FromStr>() -> T {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).ok();
    s.trim().parse().ok().unwrap()
}

fn read_vec<T: std::str::FromStr>() -> Vec<T> {
    read::<String>()
        .split_whitespace()
        .map(|e| e.parse().ok().unwrap())
        .collect()
}

fn read_touple<T: std::str::FromStr + Copy>() -> (T, T, T) {
    let v: Vec<T> = read_vec();
    assert_eq!(v.len(), 3);
    (v[0], v[1], v[2])
}

fn main() {
    let (n, m, x) = read_touple::<usize>();
    let mut cs = vec![];
    let mut xs = vec![];
    for _ in 0..n {
        let mut t: Vec<usize> = read_vec();
        cs.push(t[0]);
        t.reverse();
        t.pop();
        t.reverse();
        xs.push(t);
    }

    let bits = BitSet::empty(n);
    let mut ans = 100_000 * 100;
    for b in bits {
        let mut cost = 0;
        let vs = b.to_vec();
        let mut costs = vec![0; m];
        for (i, &j) in vs.iter().enumerate() {
            if j == 1 {
                for k in 0..m {
                    costs[k] += xs[i][k];
                }
                cost += cs[i];
            }
        }
        if check(&costs, x) {
            //dbg!(cs);
            ans = std::cmp::min(cost, ans);
        }
    }

    if ans == 100_000 * 100 {
        println!("{}", -1);
    } else {
        println!("{}", ans);
    }
}

fn check(v: &Vec<usize>, x: usize) -> bool {
    for &i in v {
        if i < x {
            return false;
        }
    }

    return true;
}

#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
struct BitSet {
    bits: usize,
    size: usize,
}

impl std::fmt::Debug for BitSet {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "BitSet {{ bits: {:b}, size: {} }}", self.bits, self.size)
    }
}

impl BitSet {
    //
    fn empty(size: usize) -> BitSet {
        if size > 64 {
            panic!("large set size")
        }
        BitSet {
            bits: 0,
            size: size,
        }
    }
    // コンンストラクター
    fn new(n: usize, size: usize) -> BitSet {
        BitSet {
            bits: n,
            size: size,
        }
    }

    // 和集合を求める
    fn union(&self, other: BitSet) -> BitSet {
        BitSet {
            bits: self.bits | other.bits,
            size: self.size, // debug
        }
    }

    // 共通部分を求める
    fn intersect(&self, other: BitSet) -> BitSet {
        BitSet {
            bits: self.bits & other.bits,
            size: self.size, // debug
        }
    }

    // n を含むかどうか
    fn include(&self, n: usize) -> bool {
        if self.size < n {
            return false;
        }
        self.bits & (1 << n) != 0
    }

    fn to_vec(&self) -> std::vec::Vec<usize> {
        let mut res = std::vec::Vec::new();
        let mut bits = self.bits;

        for _ in 0..self.size {
            res.push(bits % 2);
            bits /= 2;
        }
        res
    }

    // 集合を表すusizeの値を返す
    fn unwrap(&self) -> usize {
        self.bits
    }
}

impl Iterator for BitSet {
    type Item = BitSet;

    fn next(&mut self) -> Option<Self::Item> {
        if (1 << self.size) <= self.bits {
            return None;
        }
        self.bits += 1;
        Some(BitSet {
            bits: self.bits - 1,
            size: self.size,
        })
    }
}


Measured memory_bytes: 2160