Problem:
Score : 300 points

Problem Statement

Joisino is planning to open a shop in a shopping street.

Each of the five weekdays is divided into two periods, the morning and the evening. For each of those ten periods, a shop must be either open during the whole period, or closed during the whole period. Naturally, a shop must be open during at least one of those periods.

There are already N stores in the street, numbered 1 through N.

You are given information of the business hours of those shops, F_{i,j,k}. If F_{i,j,k}=1, Shop i is open during Period k on Day j (this notation is explained below); if F_{i,j,k}=0, Shop i is closed during that period. Here, the days of the week are denoted as follows. Monday: Day 1, Tuesday: Day 2, Wednesday: Day 3, Thursday: Day 4, Friday: Day 5. Also, the morning is denoted as Period 1, and the afternoon is denoted as Period 2.

Let c_i be the number of periods during which both Shop i and Joisino's shop are open. Then, the profit of Joisino's shop will be P_{1,c_1}+P_{2,c_2}+...+P_{N,c_N}.

Find the maximum possible profit of Joisino's shop when she decides whether her shop is open during each period, making sure that it is open during at least one period.

Constraints

1≤N≤100

0≤F_{i,j,k}≤1

For every integer i such that 1≤i≤N, there exists at least one pair (j,k) such that F_{i,j,k}=1.

-10^7≤P_{i,j}≤10^7

All input values are integers.

Input

Input is given from Standard Input in the following format:

N
F_{1,1,1} F_{1,1,2} ... F_{1,5,1} F_{1,5,2}
:
F_{N,1,1} F_{N,1,2} ... F_{N,5,1} F_{N,5,2}
P_{1,0} ... P_{1,10}
:
P_{N,0} ... P_{N,10}

Output

Print the maximum possible profit of Joisino's shop.

Sample Input 1

1
1 1 0 1 0 0 0 1 0 1
3 4 5 6 7 8 9 -2 -3 4 -2

Sample Output 1

8

If her shop is open only during the periods when Shop 1 is opened, the profit will be 8, which is the maximum possible profit.

Sample Input 2

2
1 1 1 1 1 0 0 0 0 0
0 0 0 0 0 1 1 1 1 1
0 -2 -2 -2 -2 -2 -1 -1 -1 -1 -1
0 -2 -2 -2 -2 -2 -1 -1 -1 -1 -1

Sample Output 2

-2

Note that a shop must be open during at least one period, and the profit may be negative.

Sample Input 3

3
1 1 1 1 1 1 0 0 1 1
0 1 0 1 1 1 1 0 1 0
1 0 1 1 0 1 0 1 0 1
-8 6 -2 -8 -8 4 8 7 -6 2 2
-9 2 0 1 7 -5 0 -2 -6 5 5
6 -6 7 -9 6 -5 8 0 -9 -7 -7

Sample Output 3

23

Solution in Rust (1.15.1) (judge verdict: Accepted)

#[allow(unused_macros)]
macro_rules! dump {($($e:expr), +) => {println!(concat!($(stringify!($e), " = {:?}\n"), +), $($e), +)}}
// macro_rules! max {($e0:expr, $($e:expr), +) => {{let mut r = $e0; $(r = std::cmp::max(r, $e);)+ r}}}
// macro_rules! min {($e0:expr, $($e:expr), +) => {{let mut r = $e0; $(r = std::cmp::min(r, $e);)+ r}}}
// macro_rules! freq {($v:expr) => {{let mut h = HashMap::new(); for x in $v {*h.entry(x).or_insert(0) += 1} h}}}

#[allow(unused_imports)]
use std::collections::{VecDeque, HashSet, HashMap, BinaryHeap};

fn main() {
  let n = get::val::<usize>();
  let fss = get::lists::<usize>(n);
  let pss = get::lists::<isize>(n);
  
  let profit = |c: usize| {
    let mut p = 0;
    for i in 0 .. n {
      let ref fs = fss[i];
      let ref ps = pss[i];
      let pc = (c & to_decimal(&fs)).popcount();
      p += ps[pc]
    }
    p
  };
  
  let ans = (1..1024).map(profit).max().unwrap();
  println!("{}", ans);
}
 
fn to_decimal(bs: &[usize]) -> usize {
  let mut d = 0;
  for i in bs.iter().rev().enumerate().flat_map(|(i,&b)|if b==1 {Some(i)} else {None}) {
    d.set_bit(i)
  }
  d
}

trait Bits {
  fn set_bit(&mut self, d: usize);
  fn clear_bit(&mut self, d: usize);
  fn toggle_bit(&mut self, d: usize);
  fn complement(&mut self);
  fn test_bit(&self, d: usize) -> bool;
  fn popcount(&self) -> usize;
}

#[allow(dead_code)]
impl Bits for usize {
  fn set_bit(&mut self, d: usize) {
    *self |= 1 << d
  }

  fn clear_bit(&mut self, d: usize) {
    *self &= !(1 << d)
  }

  fn toggle_bit(&mut self, d: usize) {
    *self ^= 1 << d
  }

  fn complement(&mut self) {
    *self = !*self
  }

  fn test_bit(&self, d: usize) -> bool {
    self & (1 << d) != 0
  }

  fn popcount(&self) -> usize {
    self.count_ones() as usize
  }
}

#[allow(dead_code)]
mod get {
  use std::io::*;
  use std::str::*;

  pub fn val<T: FromStr>() -> T {
    let mut buf = String::new();
    let s = stdin();
    s.lock().read_line(&mut buf).ok();
    buf.trim_right().parse::<T>().ok().unwrap()
  }

  pub fn vals<T: FromStr>(n: usize) -> Vec<T> {
    let mut vec: Vec<T> = vec![];
    for _ in 0 .. n {
      vec.push(val());
    }
    vec
  }

  pub fn tuple<T1: FromStr, T2: FromStr>() -> (T1, T2) {
    let mut buf = String::new();
    let s = stdin();
    s.lock().read_line(&mut buf).ok();
    let mut it = buf.trim_right().split_whitespace();
    let x = it.next().unwrap().parse::<T1>().ok().unwrap();
    let y = it.next().unwrap().parse::<T2>().ok().unwrap();
    (x, y)
  }

  pub fn tuples<T1: FromStr, T2: FromStr>(n: usize) -> Vec<(T1, T2)> {
    let mut vec: Vec<(T1, T2)> = vec![];
    for _ in 0 .. n {
      vec.push(tuple());
    }
    vec
  }

  pub fn tuple3<T1: FromStr, T2: FromStr, T3: FromStr>() -> (T1, T2, T3) {
    let mut buf = String::new();
    let s = stdin();
    s.lock().read_line(&mut buf).ok();
    let mut it = buf.trim_right().split_whitespace();
    let x = it.next().unwrap().parse::<T1>().ok().unwrap();
    let y = it.next().unwrap().parse::<T2>().ok().unwrap();
    let z = it.next().unwrap().parse::<T3>().ok().unwrap();
    (x, y, z)
  }

  pub fn tuple3s<T1: FromStr, T2: FromStr, T3: FromStr>(n: usize) -> Vec<(T1, T2, T3)> {
    let mut vec: Vec<(T1, T2, T3)> = vec![];
    for _ in 0 .. n {
      vec.push(tuple3());
    }
    vec
  }

  pub fn list<T: FromStr>() -> Vec<T> {
    let mut buf = String::new();
    let s = stdin();
    s.lock().read_line(&mut buf).ok();
    buf.trim_right().split_whitespace().map(|t| t.parse::<T>().ok().unwrap()).collect()
  }

  pub fn lists<T: FromStr>(h: usize) -> Vec<Vec<T>> {
    let mut mat: Vec<Vec<T>> = vec![];
    for _ in 0 .. h {
      mat.push(list());
    }
    mat
  }

  pub fn chars() -> Vec<char> {
    let mut buf = String::new();
    let s = stdin();
    s.lock().read_line(&mut buf).ok();
    buf.trim_right().chars().collect()
  }
}

#[allow(dead_code)]
mod put {
  use std::string::*;

  pub fn vec<T: ToString>(vec: &Vec<T>, sep: &str) {
    let out = vec.iter().map(|e| e.to_string()).collect::<Vec<_>>().as_slice().join(sep);
    println!("{}", out);
  }

  pub fn mat<T: ToString>(mat: &Vec<Vec<T>>, sep: &str) {
    for v in mat {
      vec(v, sep);
    }
  }
}