#![allow(dead_code)]
use crate::bit::{ones, stands};
use crate::extra::VecExtra;
use crate::scanner::Scanner;
use std::cmp::min;
fn main() {
    let mut scan = Scanner::new();
    let n = scan.read::<usize>();
    let m = scan.read::<usize>();
    let x = scan.read::<i64>();
    let mut c = vec![];
    let mut a = vec![];
    for _ in 0..n {
        c.push(scan.read::<i64>());
        let b = scan.readn::<i64>(m);
        a.push(b);
    }
    let mut ret = 1i64 << 60;
    for mask in 0..=ones(n) {
        let mut sum = 0;
        let mut status = vec![0; m];
        for i in 0..n {
            if stands(mask, i) {
                sum += c[i];
                for j in 0..m {
                    status[j] += a[i][j];
                }
            }
        }
        if status.all(|s| *s >= x) {
            ret = min(ret, sum);
        }
    }
    println!("{}", if ret == 1i64 << 60 { -1 } else { ret });
}
mod extra {
    use std::iter::{FromIterator, Sum};
    pub trait VecExtra<T> {
        fn map<B, F>(&self, f: F) -> Vec<B>
        where
            F: FnMut(T) -> B;
        fn filter<P>(&self, predicate: P) -> Vec<T>
        where
            P: FnMut(&T) -> bool;
        fn filter_map<B, F>(&self, f: F) -> Vec<B>
        where
            F: FnMut(T) -> Option<B>;
        fn any<P>(&self, predicate: P) -> bool
        where
            P: FnMut(&T) -> bool;
        fn all<P>(&self, predicate: P) -> bool
        where
            P: FnMut(&T) -> bool;
        fn sum<S>(&self) -> S
        where
            S: Sum<T>;
        fn enumerate(&self) -> Vec<(usize, T)>;
        fn to<B: FromIterator<T>>(&self) -> B;
    }
    impl<T: Clone> VecExtra<T> for Vec<T> {
        fn map<B, F>(&self, f: F) -> Vec<B>
        where
            F: FnMut(T) -> B,
        {
            self.iter().cloned().map(f).collect()
        }
        fn filter<P>(&self, predicate: P) -> Vec<T>
        where
            P: FnMut(&T) -> bool,
        {
            self.iter().cloned().filter(predicate).collect()
        }
        fn filter_map<B, F>(&self, f: F) -> Vec<B>
        where
            F: FnMut(T) -> Option<B>,
        {
            self.iter().cloned().filter_map(f).collect()
        }
        fn any<P>(&self, predicate: P) -> bool
        where
            P: FnMut(&T) -> bool,
        {
            self.iter().any(predicate)
        }
        fn all<P>(&self, predicate: P) -> bool
        where
            P: FnMut(&T) -> bool,
        {
            self.iter().all(predicate)
        }
        fn sum<S>(&self) -> S
        where
            S: Sum<T>,
        {
            Sum::sum(self.iter().cloned())
        }
        fn enumerate(&self) -> Vec<(usize, T)> {
            self.iter().cloned().enumerate().collect()
        }
        fn to<B: FromIterator<T>>(&self) -> B {
            self.iter().cloned().collect()
        }
    }
    pub trait StringExtra {
        fn to_chars(self) -> Vec<char>;
    }
    impl StringExtra for String {
        fn to_chars(self) -> Vec<char> {
            self.chars().collect()
        }
    }
}
mod bit {
    pub fn bit_filter<'a, T: Clone>(mask: usize, v: &'a [T]) -> impl Iterator<Item = T> + 'a {
        v.iter().enumerate().filter_map(move |(i, t)| {
            if (mask >> i) & 1 == 1 {
                Some(t.clone())
            } else {
                None
            }
        })
    }
    pub fn make_bit_mask(v: &[usize]) -> usize {
        let mut mask = 0usize;
        for &i in v {
            mask |= 1 << i;
        }
        mask
    }
    pub fn bit_subsets_of_subset(sup: usize) -> impl Iterator<Item = usize> {
        (sup..=sup).chain((0..).scan(sup, move |sub, _| {
            if *sub == 0 {
                return None;
            }
            *sub = (*sub - 1) & sup;
            Some(*sub)
        }))
    }
    pub fn bit_fixed_size_subsets(k: usize, n: usize) -> impl Iterator<Item = usize> {
        (0..).scan((1 << k as i64) - 1, move |x, _| {
            if k == 0 {
                return if *x == 0 {
                    *x = 1;
                    Some(0)
                } else {
                    None
                };
            }
            if !(*x < (1 << n) as i64) {
                return None;
            }
            let ret = *x as usize;
            let t = *x | (*x - 1);
            *x = (t + 1) | (((!t & -!t) - 1) >> (x.trailing_zeros() + 1));
            Some(ret)
        })
    }
    pub fn bit_supersets_of_subset(sub: usize, n: usize) -> impl Iterator<Item = usize> {
        (0..).scan(sub, move |sup, _| {
            if !(*sup < (1 << n)) {
                return None;
            }
            let ret = *sup;
            *sup = (*sup + 1) | sub;
            Some(ret)
        })
    }
    pub fn ones(n: usize) -> usize {
        (1 << n) - 1
    }
    pub fn stands(mask: usize, k: usize) -> bool {
        (mask >> k) & 1 == 1
    }
}
mod scanner {
    use std::io::{stdin, BufReader, Bytes, Read, Stdin};
    use std::str::FromStr;
    pub struct Scanner {
        buf: Bytes<BufReader<Stdin>>,
    }
    impl Scanner {
        pub fn new() -> Scanner {
            Scanner {
                buf: BufReader::new(stdin()).bytes(),
            }
        }
        pub fn read_next<T: FromStr>(&mut self) -> Option<T> {
            let token = self
                .buf
                .by_ref()
                .map(|c| c.unwrap() as char)
                .skip_while(|c| c.is_whitespace())
                .take_while(|c| !c.is_whitespace())
                .collect::<String>();
            token.parse::<T>().ok()
        }
        pub fn read<T: FromStr>(&mut self) -> T {
            self.read_next().unwrap()
        }
        pub fn readn<T: FromStr>(&mut self, n: usize) -> Vec<T> {
            (0..n).map(|_| self.read::<T>()).collect()
        }
        pub fn chars(&mut self) -> Vec<char> {
            self.read::<String>().chars().collect()
        }
    }
}



Measured memory_bytes: 2120