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 Kotlin (1.0.0) (judge verdict: Accepted)

import java.io.BufferedReader
import java.io.PrintWriter
import java.lang.StrictMath.*

var out: PrintWriter = PrintWriter(System.out)  // これを使って出力すると早い
fun main(args: Array<String>) {
    try {
        /**
         * 1. 時間1-10の1-N店舗の開店状況をIntArray(10)を1 << 10で全列挙
         *
         */
        val n = ReadLib.readInt()
        val isOpen = ReadLib.readNTimesIntArray(n)  // n, t
        val ps = ReadLib.readNTimesIntArray(n)

        fun isOpenInT(t: Int){

        }

        var max = Integer.MIN_VALUE
        for (jOpen in 1 until (1 shl 10)) {
            val isOpenCount = IntArray(n)   // 店ごとの店を開けた回数

            for (t in 0..9) {
                if (jOpen and (1 shl t) > 0) {
                    // 時間tの時jが店を開けた
                    (0 until n).forEach { isOpenCount[it] += isOpen[it][t] }
                }
            }

            val score = (0 until n).map { ps[it][isOpenCount[it]] }.sum()
            max = max(max, score)
        }
        out.println(max)
    } finally {
        out.flush()   // 消さない
    }
}


/**
 * 読み取り
 */
class ReadLib {
    companion object {
        private var reader: BufferedReader = System.`in`.bufferedReader()

        fun reset() {
            reader = System.`in`.bufferedReader()
        }

        fun readInt(): Int {
            return Integer.parseInt(reader.readLine())
        }

        // Int
        fun readIntArray(delimiters: String = " "): IntArray {
            return reader
                .readLine()
                .split(delimiters)
                .map { s -> Integer.parseInt(s) }
                .toIntArray()
        }

        fun readNTimesInt(n: Int): IntArray {
            return (1..n).map { readInt() }.toIntArray()
        }

        fun readNTimesIntArray(n: Int): Array<IntArray> {
            return (1..n).map { readIntArray() }.toTypedArray()
        }

        // long
        // TODO 別の方法を考える
        fun readLong(): Long {
            return reader.readLine().toLong()
        }

        fun readLongArray(delimiters: String = " "): LongArray {
            return reader.readLine()
                .split(delimiters)
                .map { s -> s.toLong() }
                .toLongArray()
        }

        fun readNTimesLong(n: Int): LongArray {
            return (1..n).map { readLong() }.toLongArray()
        }

        fun readString(): String {
            return reader.readLine()
        }

        fun readStringArray(delimiters: String = " "): Array<String> {
            return readString().split(delimiters).toTypedArray()
        }

        fun readNTimesCharArray(n: Int): Array<CharArray> {
            return (1..n).map { readString().toCharArray() }.toTypedArray()
        }

        fun readNTimesString(n: Int): Array<String> {
            return (1..n).map { readString() }.toTypedArray()
        }

    }
}

/**
 * 要素とその個数を出力
 */
fun <T> Array<T>.ofCountMap(): Map<T, Int> {
    return this.groupBy { it }.mapValues { it.value.count() }
}

/**
 * 文字とその個数を出力
 */
fun String.ofCountMap(): Map<Char, Int> {
    return this.toCharArray().ofCountMap()
}

/**
 * 文字とその個数を出力
 */
fun CharArray.ofCountMap(): Map<Char, Int> {
    return this.groupBy { it }.mapValues { it.value.count() }
}

/**
 * Combination, nCk mod p を求める
 * https://ja.wikipedia.org/wiki/%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%A9%E9%80%86%E6%95%B0
 * http://drken1215.hatenablog.com/entry/2018/06/08/210000
 * @param maxN 最大のn
 * @param mod 素数p
 */
class ModCombination(private val maxN: Int, private val mod: Int = 1000000007) {
    private val fac: IntArray = IntArray(maxN)
    private val finv: IntArray = IntArray(maxN)

    init {
        val inv: IntArray = IntArray(maxN)
        fac[0] = 1
        fac[1] = 1

        inv[0] = 1
        inv[1] = 1
        for (i in 2..maxN) {
            fac[i] = fac[i - 1] * i % mod   // 累積
            // mod % i < i
            inv[i] = mod - ((inv[mod % i].toLong()) * (mod / i) % mod).toInt()
            finv[i] = finv[i - 1] * inv[i] % mod
        }
    }

    /**
     * nCk mod p
     */
    fun Calc(n: Int, k: Int): Int {
        if (n < k || n < 0 || k < 0) {
            return 0
        }

        return ((fac[n].toLong() * finv[k] % mod) * finv[n - k] % mod).toInt()
    }
}

class MyMath {
    companion object {
        // 最大公約数
        fun gcd(m: Long, n: Long): Long {
            var M = m
            var N = n
            while (M % N > 0) {
                val pN = N
                N = M % N
                M = pN
            }

            return N
        }

        fun lcm(m: Long, n: Long): Long {
            return (m / gcd(m, n)) * n
        }

        // 素因数分解（試し割り）
        // http://sucrose.hatenablog.com/entry/2014/10/10/235805
        fun primeFactorization(n: Long): Map<Long, Long> {
            val primes = enumeratePrime(ceil(sqrt(n.toDouble())).toInt())
                .map { it.toLong() }
                .toLongArray()
            primes.sort()

            val counter = mutableMapOf<Long, Long>()
            var cn = n
            for (p in primes) {
                if (cn < p) {
                    break
                }

                while (cn % p == 0L) {
                    counter[p] = counter.getOrElse(p, { 0 }) + 1
                    cn /= p
                }
            }

            if (cn > 1) {
                counter[cn] = 1
            }

            return counter
        }

        // Nまでの素数列挙
        fun enumeratePrime(n: Int): IntArray {
            val isPrime = BooleanArray(n + 1) { true }
            val primes = mutableListOf<Int>()
            for (i in 2..n) {
                if (!isPrime[i]) {
                    continue
                }

                primes.add(i)
                for (j in i..n step i) {
                    isPrime[i] = false
                }
            }

            return primes.toIntArray()
        }
    }
}