首页 > 试题广场 >

小心火烛的歪

[编程题]小心火烛的歪
  • 热度指数:5520 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 512M,其他语言1024M
  • 算法知识视频讲解
\hspace{15pt}小歪正在一个占地 n \times m 大小的草地上研究他的燃放烟花计划。其中,一些位置已经堆放了杂物,为了便于观察,我们将给出一个 n \times m 大小的字符矩阵描述草地。其中,堆放了杂物的位置使用数字 1 标注;其余位置使用数字 0 标注。
\hspace{15pt}小歪已经做好了若干个烟花燃放计划,每一个计划均为一个 n \times m 大小的字符矩阵,一一对应草地的每一个方格。在这个计划中,将会被燃放烟花的地块使用数字 1 标注;没有烟花的地块使用数字 0 标注。
\hspace{15pt}他想选择一些计划同时实施,如果某个地块在任意一个计划中被标注为燃放,那么这个地块就会真的燃放上烟花。小歪想要知道,是否存在这样一种选择方法,使得全部有杂物位置均不会燃放烟花,而没有杂物的位置全部燃放上烟花;如果存在,请输出最少数量的计划。

输入描述:
\hspace{15pt}第一行输入三个整数 n,m,q \left( 1 \leqq n,m,q \leqq 7 \right) 代表草地的长、草地的宽、计划数量。
\hspace{15pt}此后 n 行,每行输入 m 个字符,代表草地初始状态。
\hspace{15pt}此后 n \times q 行,每行输入 m 个字符,用于描述计划。
\hspace{15pt}全部字符仅为数字 \texttt{0}\texttt{1}


输出描述:
\hspace{15pt}如果不存在满足要求的燃放方案,直接输出 -1

\hspace{15pt}否则,请按如下格式输出:
\hspace{15pt}第一行上输出一个整数 p \left( 0 \leqq p \leqq q \right) 代表使用到的计划数量。
\hspace{15pt}第二行输出 p 个整数代表你所选择的计划编号。编号即输入顺序,从 1 开始计数。

\hspace{15pt}如果存在多个解决方案,您可以输出任意一个,系统会自动判定是否正确。注意,自测运行功能可能因此返回错误结果,请自行检查答案正确性。
示例1

输入

2 2 1
00
01
11
10

输出

1
1
示例2

输入

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

说明

\hspace{15pt}草地初始状态如下图所示。在这个样例中,选择 1,2,3,5 也是一个合法的答案。

这是简单题???
发表于 2025-09-19 17:50:47 回复(0)
from itertools import combinations
n, m, q = map(int, input().split())
cond = []
sum_cond = 0
for i in range(n):
    temp = list(map(int, list(input())))
    sum_cond += sum(temp)
    cond.append(temp)

plan = []
avail = []
for i in range(q):
    plan_ = []
    avail_ = 1
    for j in range(n):
        temp = list(map(int, list(input())))
        plan_.append(temp)
        if 2 in [temp[k]+cond[j][k] for k in range(m)]:
            avail_ = 0
    plan.append(plan_)
    if avail_:
        avail.append(i)

def is_valid(plan, comb, cond):
    temp = cond.copy()
    for p in range(len(comb)):
        plan_ = plan[comb[p]]
        for i in range(n):
            temp[i] = [temp[i][j]+plan_[i][j] for j in range(m)]
    for i in range(n):
        if 0 in temp[i]:
            return False
    return True

if sum_cond == n*m:
    print(0)
else:    
    sum = cond.copy()
    for i in range(n):
        for j in range(q):
            if j in avail:
                sum[i] = [sum[i][k] + plan[j][i][k] for k in range(m)]
               
    unavail = 0
    for i in range(n):
        if 0 in sum[i]:
            unavail = 1
            break

    found = 0
    if unavail == 1:
        print(-1)
    else:
        for num in range(1, 1+len(avail)):
            for comb in combinations(avail, num):
                if is_valid(plan, comb, cond):
                    print(num)
                    print(' '.join(map(str, [comb[i]+1 for i in range(len(comb))])))
                    found = 1
                    break
            if found == 1:
                break


发表于 2025-07-18 00:44:02 回复(0)
#最优解如何实现呢?
n,m,q=list(map(int,input().split()))
s = []
re = []
res = []
for i in range(1,n*q+n+1):
    x = 0
    low = list(map(int,input()))
    re.append(low)
    if i % n == 0:
        s.append(re)
        re = []
start = s[0]
s = s[1:]
i = 0

while i < q:#排除杂物位置燃放烟花的计划
    x = s[i]
    flag = 0
    exit_ = False
    for j in range(n):
        for k in range(m):
            if x[j][k] == 1 and start[j][k] == 1:
                exit_ = True
                break
        if exit_:
            break   
    if not exit_ : 
        res.append(i)
    i += 1

l = []
z = 0
for i in range(n):
    for j in range(m):
        if start[i][j]==0:
            z = 1
if z ==0:
    print('0')
elif z == 1 and  len(res) == 0:
    print('-1')
else:
    y = 0
    while y <len(res):
        p = res[y]
        r = s[p]
        for i in range(n):
            for j in range(m):
                if r[i][j] == 1:
                    start[i][j] = 1
                else:
                    continue
        l.append(str(p+1))
        flag = 0
        for k in range(n):
            for v in range(m):
                if start[k][v]==0:
                    flag = 1

        if flag == 1 and y == len(res)-1:
            print('0')
        if flag==0:
            print(len(l))
            print(' '.join(l))
            break
        if flag == 1:
            y += 1

发表于 2025-06-07 11:11:35 回复(0)
# 将初始状态与计划都转化为数字,通过相加,为0的位置表示没有杂物也没有烟花,通过计划与初始状态依次相加,检查有无‘2’,排除烟花与杂物重合的计划,用itertools.combinations枚举所有的计划组合情况
# 同一个位置可以有多个烟花,因此最后 不能依靠相加后全为‘1’判断,而是是否有‘0’,且由于存在前置‘0’缺失会导致判断出现错误,如‘0001’转化成数字会变成‘1’,因此需要判断字符串长度是否符合
 
importitertools
 
n, m, q = map(int, input().split())
chushi =""
for_ in range(n):
    chushi += input()
 
# 若初始没有0,则不需要计划,输出0
ifchushi.count("0") ==0:
    print(0)
    exit()
 
chushi =int(chushi)
 
jihua = []
for_ in range(q):
    tem =""
    for_ in range(n):
        tem += input()
    jihua.append(int(tem))
 
# 筛选计划,若存在与初始重叠的就排除,找出可行的计划
kexin = {}
fori in range(q):
    ifstr(chushi + jihua[i]).count("2") ==0:
        kexin[i +1] = jihua[i]
 
# 若没有可行的计划或计划没有燃放的位置就输出-1
iflen(kexin) ==0or max(kexin.values()) ==0:
    print(-1)
 
else:
    found = False
    fori in range(1, q +1):
        forfangan in itertools.combinations(kexin.keys(), i):
            shishi = chushi
            forj in fangan:
                shishi += kexin[j]
            # 初始加计划后全部位置都没有空,且长度为n*m防止由于前置0缺失导致原本不可行的方案可行,如001变为1
            ifstr(shishi).count("0") ==0and len(str(shishi)) == n * m:
                print(i)
                print(" ".join(map(str, fangan)))
                found = True
                break
        iffound:
            break

作者:在笔试的柠檬精很不想上
链接:https://www.nowcoder.com/discuss/755840988169383936?sourceSSR=users
来源:牛客网
发表于 2025-05-24 17:23:38 回复(0)
from itertools import combinations

def generate_blank_matrix(n, m):
    return [[0 for _ in range(m)] for _ in range(n)]

def read_matrix(n):
    matrix = [[] for _ in range(n)]
    for i in range(n):
        matrix[i] = list(map(int, list(input().strip())))
    return matrix

def matrix_max(m1, m2):
    """ 两个位矩阵取取并(即“或”运算) """
    matrix = [[] for _ in range(len(m1))]
    for i in range(len(m1)):
        matrix[i] = [max(x,y) for x, y in zip(m1[i], m2[i])]
    return matrix

def matrix_is_comp(m1, m2):
    """ 判断两个位矩阵是否互补 """
    is_comp = True
    done = False
    for i in range(len(m1)):
        for j in range(len(m1[0])):
            if m1[i][j] + m2[i][j] != 1:
                is_comp = False
                done = True
                break
        if done:
            break
    return is_comp

def get_min_plan(n, m, dct_ms, m0):
    """ 按元素个数依次枚举 """
    for r in range(1, len(dct_ms)+1):
        for comb in combinations(dct_ms.keys(), r):
            # 1.merge these matrixes
            mtx = generate_blank_matrix(n, m)
            for idx in comb:
                mtx = matrix_max(mtx, dct_ms[idx])
            # 2.judge if complement
            if matrix_is_comp(mtx, m0):
                return list(comb)
    return []

# 1.read data
n, m, q = map(int, input().strip().split())
# main matrix
m0 = read_matrix(n)
# plan matrixes
dct_ms = {}
id_m = 0
for _ in range(q):
    id_m += 1
    dct_ms[id_m] = read_matrix(n)

# 2.compute and print
mtx = generate_blank_matrix(n, m)
if matrix_is_comp(mtx, m0):
    # m0 already full
    print(0)
else:
    # m0 not full
    lst_id = get_min_plan(n, m, dct_ms, m0)
    if lst_id:
        print(len(lst_id))
        lst_id.sort()
        print(" ".join(map(str, lst_id)))
    else:
        print(-1)


发表于 2025-05-21 19:33:12 回复(0)