const readline = require("readline");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
const tokens: string[] = [];
rl.on("line", function (line) {
tokens.push(line.trim());
}).on("close", function () {
const [n, m, q] = tokens.shift().split(" ").map(Number);
const ground: number[][] = [];
for (let i = 0; i < n; ++i) {
ground.push(tokens.shift().split("").map(Number));
}
if (isAllOnes(ground, n, m)) {
/** 草地全为杂物, 选零个计划 */
console.log(0);
} else {
/** 把计划全挑出来 */
const plans: number[][][] = [];
while (tokens.length !== 0) {
const plan: number[][] = [];
let i = 0;
while (i < n) {
plan.push(tokens.shift().split("").map(Number));
++i;
}
plans.push(plan);
}
let count = -1,
planCodes: number[] = [],
minPlans = Number.MAX_VALUE;
/** 从第一个计划开始遍历 */
for (let i = 0; i < q; ++i) {
if (isValidPlan(plans[i], ground, n, m)) { // 该计划符合要求,进行下一步处理
/** 初始化一个空计划 */
let tmpGround: number[][] = Array.from({ length: n }, () =>
Array(m).fill(0)
),
tmpPlanCodes: number[] = [i + 1]; // 添加第一个符合要求的计划编号
addPlan(plans[i], tmpGround, n, m); // 把第一个符合要求的计划添加进来
let tmpCount = 1, // 已选择的计划数量为 1
j = i + 1;
/** 挑选后续合格的计划,直到把原草地的空地填满为止 */
while (j < q && !isValidResolvedGround(tmpGround, ground, n, m)) {
if (isValidPlan(plans[j], ground, n, m)) {
addPlan(plans[j], tmpGround, n, m);
tmpPlanCodes.push(j + 1);
++tmpCount;
}
++j;
}
if (isValidResolvedGround(tmpGround, ground, n, m)) {
i = --j;
/** 去重 把多余的计划减掉*/
for (let k = 0; k < tmpPlanCodes.length; ++k) {
removePlan(plans[tmpPlanCodes[k] - 1], tmpGround, n, m);
if (isValidResolvedGround(tmpGround, ground, n, m)) {
//减掉该计划后,依然满足要求,把该计划编号从已挑选列表中删除, 计划数减 1
tmpPlanCodes.splice(k, 1);
--k;
--tmpCount;
} else {
// 减掉该计划后不满足要求,把它重新添加回来
addPlan(plans[tmpPlanCodes[k] - 1], tmpGround, n, m);
}
}
if (tmpCount < minPlans) {
planCodes = tmpPlanCodes;
count = minPlans = tmpCount;
}
}
}
}
console.log(count);
console.log(planCodes.join(" "));
}
});
function isAllOnes(ground: number[][], n: number, m: number): boolean {
for (let i = 0; i < n; ++i) {
for (let j = 0; j < m; ++j) {
if (ground[i][j] === 0) return false;
}
}
return true;
}
function isValidPlan(
plan: number[][],
ground: number[][],
n: number,
m: number
): boolean {
for (let i = 0; i < n; ++i) {
for (let j = 0; j < m; ++j) {
if (plan[i][j] === 1 && ground[i][j] === 1) return false;
}
}
return true;
}
/** 之所以用数字累加的方式,是为了方便后续处理去重逻辑 */
function addPlan(
plan: number[][],
resolvedGround: number[][],
n: number,
m: number
) {
for (let i = 0; i < n; ++i) {
for (let j = 0; j < m; ++j) {
resolvedGround[i][j] += plan[i][j];
}
}
}
function removePlan(
plan: number[][],
resolvedGround: number[][],
n: number,
m: number
) {
for (let i = 0; i < n; ++i) {
for (let j = 0; j < m; ++j) {
resolvedGround[i][j] -= plan[i][j];
}
}
}
/** 检查已挑选计划处理过后的草地,在原草地的空地上对应的值是否大于 0,如果依然为 0,说明这些计划还不足以解决 */
function isValidResolvedGround(
resovedGround: number[][],
ground: number[][],
n: number,
m: number
): boolean {
for (let i = 0; i < n; ++i) {
for (let j = 0; j < m; ++j) {
if (ground[i][j] === 0 && resovedGround[i][j] === 0) return false;
}
}
return true;
}