第一行输入三个整数
代表草地的长、草地的宽、计划数量。
此后
行,每行输入
个字符,代表草地初始状态。
此后
行,每行输入
个字符,用于描述计划。
全部字符仅为数字
或
。
如果不存在满足要求的燃放方案,直接输出
。
否则,请按如下格式输出:
第一行上输出一个整数
代表使用到的计划数量。
第二行输出
个整数代表你所选择的计划编号。编号即输入顺序,从
开始计数。
如果存在多个解决方案,您可以输出任意一个,系统会自动判定是否正确。注意,自测运行功能可能因此返回错误结果,请自行检查答案正确性。
2 2 1 00 01 11 10
1 1
7 7 5 1110111 1111111 1100001 0101000 1100001 1111111 1110111 0001000 0000000 0000000 1000001 0000000 0000000 0001000 0000000 0000000 0011100 0000000 0011100 0000000 0000000 0000000 0000000 0000010 0000111 0000010 0000000 0000000 0000000 0000000 0010000 0010000 0010000 0000000 0000000 0000000 0000000 0010000 0010111 0010000 0000000 0000000
4 1 2 3 4
草地初始状态如下图所示。在这个样例中,选择
也是一个合法的答案。
import sys
# 处理过程用到的数据结构是二维的 bool 块
# 为了理解和思考方便,假设草地为 1 * m (011...)
# 然后这 1 行 bool 可以看成二进制表达的数字
# 那么草地杂物用数字 x 来表示,燃放计划用数字 y 来表示
#
# 想要杂物位置上不能放烟花,而所有空位都放烟花:
# 就是 x 的所有为 1 的位上,y 必须为 0;
# 而 x 的所有为 0 的位上,y 必须为 1
# 也就是 x | y == 0b(1111...) 且 x & y == 0
# 那么 y = x ^ 0b(1111...)
# 多个燃放计划一起执行:
# 那么总计划的值为 yn = y1 | y2 | y3 ...
#
# 所以这个题目可以简化为:
# 在 y1, y2, y3, ..., yn 中, 找到最少数量的 y (a, b, c...), 使得
# (ya | yb | yc | ...) == x ^ 0b(1111...)
# 在 planInfos 中找到能满足 target 的合并的方案
# planInfos: 所有固定的方案
# idx: planInfos 的下标,这个下标前面的方案已经考虑过,后面的方案等待考虑
# clutterInfo: 杂物信息
# target: 所有合并的方案要满足的目标
# mergedInfo: 已经合并好的方案
# planStr: 已选入的所有方案的下标的字符串
#
# return (bool, str): 只要一找到合适的方案,马上就返回
def findPlans(planInfos, idx, clutterInfo, target, mergedInfo, planStr):
if idx == len(planInfos):
return (False, '')
plan = planInfos[idx]
if plan & clutterInfo != 0: # 这个方案与杂物冲突,直接跳到下一个方案去计算
return findPlans(planInfos, idx+1, clutterInfo, target, mergedInfo, planStr)
if plan | mergedInfo == target: # 找到了方案
return (True, planStr + ' ' + str(idx + 1))
# 既然要找最少的方案数量,倾向于先不选择当前方案
b1 = findPlans(planInfos, idx+1, clutterInfo, target, mergedInfo, planStr)
if b1[0]: return b1
# 再考虑加上当前的方案
return findPlans(planInfos, idx+1, clutterInfo, target, mergedInfo | plan, planStr + ' ' + str(idx + 1))
# 提取草地特征,或者提取燃放计划的特征
# 题目说 n, m <= 7, 那么 n * m < 64, 草地信息用 64 位存储就够了,用 int 肯定可以
def extractFeatures(lines: list[str]) -> int:
feature = 0
for line in lines:
for ch in line:
bit = 1 if ch == '1' else 0
feature = (feature << 1) + bit
return feature
n, m, q = map(int, input().split(' '))
clutterInfo = 0
planInfos = [0] * q
for i in range(q + 1):
lines = []
for _ in range(n):
lines.append(input().strip())
if i == 0:
# 第一个块是杂物的信息
clutterInfo = extractFeatures(lines)
else:
# 后面的块是烟花信息
planInfos[i-1] = extractFeatures(lines)
# 全为 1 的草地
allFull = (1 << (n*m)) - 1
target = clutterInfo ^ allFull
res = findPlans(planInfos, 0, clutterInfo, target, 0, '')
if res[0]:
count = res[1].count(' ')
print(count)
print(res[1].strip())
else:
print(0)
import java.util.Scanner;
import java.io.*;
// 数据很小, 回溯枚举检查:可以使用 位运算 + 状态压缩
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] sp = br.readLine().split(" ");
int n = Integer.parseInt(sp[0]);
int m = Integer.parseInt(sp[1]);
int q = Integer.parseInt(sp[2]);
int[] grass = new int[n]; // 草地n行, 合并每行的宽仅1个数表示
for (int i = 0; i < n; i++) {
grass[i] = Integer.parseInt(br.readLine(), 2); // 01字符串转int
}
int[][] plans = new int[q][n]; // q个计划
for (int k = 0; k < q; k++) {
for (int i = 0; i < n; i++) {
plans[k][i] = Integer.parseInt(br.readLine(), 2);
}
}
int min = Integer.MAX_VALUE, res = 0;
next:
for (int i = 0; i < (1 << q); i++) { // q个计划, [0, 2^q-1]种状态 00..00 ~ 11..11
int cnt = 0;
int[] p = new int[n];
for (int x = i, k = 0; x > 0; x >>= 1, k++) {
if ((x & 1) == 1) { // 对于特定状态i, 二进制1 取计划
cnt++;
if (!check1(grass, plans[k])) continue next;
for (int j = 0; j < n; j++) {
p[j] |= plans[k][j];
}
}
}
if (check2(grass, p, m)) { // 非杂物部分的0 都填满1
if (cnt < min) {
min = cnt;
res = i;
}
}
}
StringBuilder sb = new StringBuilder(); // 处理结果
if (min == Integer.MAX_VALUE) {
sb.append(-1);
} else {
sb.append(min).append('\n');
for (int i = 0; res > 0; i++, res >>= 1) {
if ((res & 1) == 1) {
sb.append(i + 1).append(' ');
}
}
}
System.out.print(sb.toString());
}
// 检查plan没有点燃grass杂物:plan[i] & gras[i]==0
private static boolean check1(int[] grass, int[] plan) {
for (int i = 0; i < grass.length; i++) {
if ((grass[i] & plan[i]) > 0) return false;
}
return true;
}
// 检查plan填满grass非杂物部分:plan[i] | gras[i]== (1<<m)-1
private static boolean check2(int[] grass, int[] plan, int m) {
for (int i = 0; i < grass.length; i++) {
if ((grass[i] | plan[i]) != (1 << m) - 1) return false;
}
return true;
}
} using System;
using System.Linq;
using System.Collections.Generic;
public class Program {
public static void Main() {
var line = Console.ReadLine ().Split(' ').Select(x => int.Parse(x)).ToList();
int n = line[0];
int m = line[1];
int q = line[2];
int[,] grass = new int[n, m];// 草地状态、
int idleNum = 0;
for (int i = 0; i < n; i++) {
var temp = Console.ReadLine ().Select(x => int.Parse(x.ToString())).ToList();
for (int j = 0; j < m; j++) {
grass[i, j] = temp[j];
if (temp[j] == 0) {
idleNum += 1;
}
}
}
if(idleNum==0){// 检查是否有空位
Console.WriteLine(0);
return;
}
List<int[,]> plans = new List<int[,]>();
for (int k = 0; k < q; k++) {
int[,] plan = new int[n, m];// 计划
bool can=true;// 标识计划是否可被执行
for (int i = 0; i < n; i++) {
var temp = Console.ReadLine ().Select(x => int.Parse(x.ToString())).ToList();
for (int j = 0; j < m; j++) {
plan[i, j] = temp[j];// 检查计划是否可执行
if(plan[i, j]==1&&grass[i,j]==1){
can=false;
}
}
}
if(can){
plans.Add(plan);
}
}
bool isEnd = false;
HashSet<int> res=new HashSet<int>();
for (int i = 0; i < plans.Count; i++) { // 遍历每一个计划
if (!isEnd) {
for (int j = 0; j < n; j++) {
for (int k = 0; k < m; k++) { // 遍历计划的每一个位置
// 是否等于1,以及草地是否空,是则放置烟花
if (plans[i][j, k] == 1 && grass[j, k] == 0&&idleNum>0) {
grass[j, k] = 1;
res.Add(i+1);
idleNum--;
if (idleNum == 0) {// 放置完成
isEnd=true;
}
}
}
}
}else{//
break;
}
}
if(!isEnd){
Console.WriteLine(-1);
}else{
Console.WriteLine(res.Count);
Console.WriteLine(string.Join(" ", res));
}
//Console.WriteLine(plans.Count);
}
} #include <bits/stdc++.h>
using namespace std;
int main() {
int n,m,q;
cin>>n>>m>>q;
vector<string> v(n);
int an[100];
string s;
for(auto &c:v)cin>>c;
int sum=0;
for(int i=0;i<q;i++){
int f=1;
for(int j=0;j<n;j++){
cin>>s;
bitset<32> b1(s);
bitset<32> b2(v[j]);
bitset<32> b3(b1&b2);
if((b1.count()+b2.count())==b3.count()){
f=0;
break;
}
}
if(f){
sum++;
an[i]=i+1;
}
}
if(!sum)cout<<-1;
else{
cout<<sum<<endl;
for(int i=0;i<sum;i++)cout<<an[i]<<" ";
}
} import java.util.Scanner;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int m=in.nextInt(),n=in.nextInt(),q=in.nextInt();in.nextLine();
int [][]grass=new int[m][n];
for(int i=0;i<m;++i){
String g1=in.nextLine();
for(int j=0;j<n;++j){
grass[i][j]=Integer.parseInt(""+g1.charAt(j));
}
}
int [][]an=new int[m][n];
// int [][]temp=new int[m][n];
ArrayList<combine> alist=new ArrayList<>();
for(int k=0;k<q;++k){
for(int i=0;i<m;++i){
String g1=in.nextLine();
for(int j=0;j<n;++j){
an[i][j]=Integer.parseInt(""+g1.charAt(j));
}
}
alist.add(new combine(m,n,an));
}
ArrayList<Integer> listbags=new ArrayList<>();
for(int i=0;i<q;++i){
listbags.add(i+1);
}
bags(new combine(m,n,grass),new ArrayList<combine>(),alist,new boolean[q],listbags,new combine(m,n,grass));
int allzero[][]=new int[m][n];
combine zero=new combine(m,n,allzero);
for(int i=0;i<q;++i){
if(isconOk(alist.get(i),new combine(m,n,grass))){
zero=zero.Numberadd(alist.get(i));
}
}
if(!isFull(m,n,zero.Numberadd(new combine(m,n,grass)))){
System.out.println(-1);
}
else{System.out.println(listbags.size());
for(int i=0;i<listbags.size();++i){
System.out.print(listbags.get(i)+" ");
}}
}
private static void bags(combine now,ArrayList<combine> bagsnow,ArrayList<combine> total,boolean used[],ArrayList<Integer>usedbag,combine beginner){
if(isFull(now.a.length,now.a[0].length,now)&&usedbag.size()>lenused(used)){
ArrayList<Integer>temp=new ArrayList<>();
temp=boltoArr(used);
usedbag.clear();
usedbag.addAll(temp);return;
}
for(int i=0;i<total.size();++i){
if(!used[i]&&isconOk(total.get(i),beginner)){
used[i]=true;
bagsnow.add(total.get(i));
bags(now.Numberadd(total.get(i)),bagsnow,total,used,usedbag,beginner);
bagsnow.remove(bagsnow.size()-1);
used[i]=false;
}
}
}
private static boolean isconOk(combine a,combine b){
combine c=a.Numberadd(b);
for(int i=0;i<c.a.length;++i){
for(int j=0;j<c.a[0].length;++j){
if(c.a[i][j]>=2)return false;
}
}
return true;
}
private static int lenused(boolean[]used){
int count=0;
for(int i=0;i<used.length;++i){
if(used[i]){
count++;
}
}
return count;
}
private static ArrayList<Integer> boltoArr(boolean[] used){
ArrayList<Integer> alist=new ArrayList<>();
for(int i=0;i<used.length;++i){
if(used[i]){
alist.add(i+1);
}
}
return alist;
}
private static boolean isFull(int m,int n,combine a){
for(int i=0;i<m;++i){
for(int j=0;j<n;++j){
if(a.a[i][j]==0){
return false;
}
}
}
return true;
}
}
class combine{
int a[][];
combine(int m,int n,int a[][]){
int an[][]=new int[m][n];
for(int i=0;i<m;++i){
System.arraycopy(a[i],0,an[i],0,n);
// for(int j=0;j<n;++j){
// this.a[i][j]=a[i][j];
// }
}
this.a=an;
}
public combine Numberadd(combine b){
int m=this.a.length,n=this.a[0].length;
int c[][]=new int[m][n];
for(int i=0;i<m;++i){
for(int j=0;j<n;++j){
c[i][j]=this.a[i][j]+b.a[i][j];
}
}
combine retc=new combine(m,n,c);
return retc;
}
} n,m,q = list(map(int,input().split()))
A = [list(map(int,input())) for _ in range(n)]
all_ones = True
for row in A:
if any(bit == 0 for bit in row):
all_ones = False
break
if all_ones:
print(0)
exit()
target_bits = []
for row in A:
bits = 0
for bit in row:
bits = (bits<<1) | (1-bit) #取反:0->1,1->0
target_bits.append(bits)
valid_meth = []
meth_bits = []
for i in range(q):
meth_q = [list(map(int,input())) for _ in range(n)]
is_valid = True
for row in range(n):
for col in range(m):
if A[row][col] == 1 and meth_q[row][col] == 1:
is_valid = False
break
if not is_valid:
break
if is_valid:
valid_meth.append(i)
mbits = []
for row in meth_q:
bits = 0
for bit in row:
bits = (bits << 1) | bit #保存满足要求的矩阵
mbits.append(bits)
meth_bits.append(mbits) #多个矩阵列表
if not valid_meth:
print(-1)
else:
from itertools import combinations
min_count = float('inf')
best_comb = []
best_combs = []
for r in range(1,len(valid_meth) + 1):
for comb in combinations(range(len(valid_meth)),r):
union = [0] * n #每个元素表示一行的覆盖情况
for idx in comb:
mbits = meth_bits[idx] #获取子矩阵的二进制表示
for j in range(n):
union[j] |= mbits[j]
cover_all = True
for j in range(n):
if (union[j] & target_bits[j]) != target_bits[j]:
cover_all = False
break
if cover_all:
if r < min_count:
min_count = r
best_combs = [[valid_meth[i] for i in comb]]
elif r == min_count:
best_combs.append([valid_meth[i] for i in comb]) # 添加新组合
break
if min_count != float('inf'):
break
if min_count == float('inf'):
print(-1)
else:
print(min_count)
print(' '.join(map(lambda x: str(x + 1), sorted(best_combs[0]))))