首页 > 试题广场 >

小心火烛的歪

[编程题]小心火烛的歪
  • 热度指数:6069 时间限制: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-10-11 20:50:17 回复(1)
我的两个失误:1、没意识到空地可重复放烟花。2、使用递归当遇到在非空地放烟花的情况别直接return,不然后面的方案就不能被考虑到了。
发表于 2025-05-05 20:15:30 回复(0)
这不就是揭幕者们小游戏吗
发表于 2025-11-13 10:40:46 回复(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)
//成功啦 自己做不出来的原因 在于 烟花计划有共同的1!!!即燃放位置  这样是可以的 符合题意 例如例题里那样的  如何解决这个问题 就欧克la

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    private static class plan {
        long mask;
        int id;
        plan(long mask, int id) {
            this.mask = mask;
            this.id = id;
        }
    }
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        int n = in.nextInt();
        int m = in.nextInt();
        int q = in.nextInt();
        in.nextLine();
        String[] a = new String[n];//记录草坪原始状态
        for (int i = 0; i < n; i++) {
            a[i] = in.nextLine();
        }
        //对草坪进行目标掩码处理 以及 把杂物位置拿出来
        long targetmask = 0;
        List<int[]> b = new ArrayList<>();
        int pos = 0;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (a[i].charAt(j) == '1') {
                    b.add(new int[] {i, j});
                } else {
                    pos = i * m + j;
                    targetmask = targetmask | 1L << pos;
                }
            }
        }
        //好的方法如下 简洁又易懂
        List<plan> c = new
                ArrayList<>(); //存放满足杂物位置的计划 待排序组合
        for (int i = 0; i < q; i++) {
            List<String> d = new ArrayList<>();
            for (int j = 0; j < n; j++) {
                d.add(in.nextLine());
            }
            boolean NO = false;
            for (int[] k : b) { //遍历放杂物的 获取所有的xy值
                int x = k[0];
                int y = k[1];
                if (d.get(x).charAt(y) == '1') {
                    NO = true;
                    break;
                }
            }
            if (NO) {
                continue;
            }
            //通过的烟花计划开始处理 计算目标掩码 并和id一起存储到类Class中
            long mask = 0;
            for (int j = 0; j < n; j++) {
                String x = d.get(j);
                for (int k = 0; k < m; k++) {
                    if (x.charAt(k) == '1') {
                        pos = j * m + k; //0,0 1,0 0,1  0 1 2  01 10 100
                        mask = mask | 1L << pos;
                    }

                }
            }
            c.add(new plan(mask, i + 1));
        }
        /*
        //这部分是可以的 是自己使用自己的方法找到复合条件烟花计划的 并存储 但是时间上更复杂了 因为等于遍历了所有烟花位置与花坪位置比较 看是否为0  但是上面那个方法只找了杂物位置是否放烟花
        //要把List<int[]> b = new ArrayList<>();修改为 int[][] b = new int[n][m];
        //然后开始筛选烟花计划 排除在杂物中 放烟花计划
        List<plan> c =new ArrayList<>();//存放满足杂物位置的计划 待排序组合
        for(int i = 0;i<q;i++){//有q组
            boolean NO = false;
            long mask = 0;
            pos = 0;
            for(int j = 0;j<n;j++){
                String x = in.nextLine();
                if(NO){
                    continue;
                }
                for(int k = 0;k<m;k++){
                    if(b[j][k]=='1'&&x.charAt(k)=='1'){
                        NO = true;
                        break;
                    }else if(x.charAt(k)=='1'){
                        pos = j*m+k;
                        mask = mask | 1L<<pos;
                    }
                }
            }
            c.add(new plan(mask,i+1));//这里特别注意哦 !!添加成功的烟花计划
        }
        */
        if (targetmask == 0) {
            System.out.println(0);
            return;
        }
        if (c.isEmpty()) { //如果都没有符合的 输出-1并终止程序运行啦
            System.out.println(-1);
            return;
        }        
        //现在我们已经筛选完合适的烟花计划了 该开始组合了 总组合次数= 2^烟花计划次方 -1
        int mincount = Integer.MAX_VALUE;
        List<Integer> minyanhua = null;
        for (int i = 1; i < (1<<c.size()); i++) {
            long mask = 0;
            List<Integer> yanhua = new ArrayList<>();
            for (int j = 0; j < c.size(); j++) {
                if ((i & (1 << j)) != 0) {
                    mask = mask | c.get(j).mask;
                    yanhua.add(c.get(j).id);
                }
            }
            if (mask == targetmask) {
                if (yanhua.size() < mincount) {
                    mincount = yanhua.size();
                    minyanhua = yanhua;
                }
            }
        }//这里遍历组合了所有烟花排序 来看结果 如果都没有 就说明都没有符合的 如果有就输出
        if (minyanhua==null) {
            System.out.println(-1);
        } else {
            System.out.println(mincount);
            for (int i = 0; i < minyanhua.size(); i++) {
                System.out.print(minyanhua.get(i)+" ");
            }
        }
        /*
                System.out.println(targetmask);
                for(int i = 0;i<c.size();i++){
                    System.out.println(c.get(i).mask);
                    System.out.println(c.get(i).id);
                }
                for(int i = 0;i<n;i++){
                    System.out.println(a[i]);
                }

                for(int i = 0;i<n;i++){
                    for(int j = 0;j<m;j++){
                        System.out.print(b[i][j]+" ");
                    }
                    System.out.println();
                }

                */
    }
}
发表于 2025-03-23 23:11:50 回复(3)
package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	
	// Read first line: n, m, q
	scanner.Scan()
	firstLine := strings.Split(scanner.Text(), " ")
	n, _ := strconv.Atoi(firstLine[0])
	m, _ := strconv.Atoi(firstLine[1])
	q, _ := strconv.Atoi(firstLine[2])
	
	// Read initial state
	initialState := make([][]int, n)
	for i := 0; i < n; i++ {
		scanner.Scan()
		line := scanner.Text()
		initialState[i] = make([]int, m)
		for j := 0; j < m; j++ {
			initialState[i][j] = int(line[j] - '0')
		}
	}
	
	// Read plans
	plans := make([][][]int, q)
	for planIdx := 0; planIdx < q; planIdx++ {
		plans[planIdx] = make([][]int, n)
		for i := 0; i < n; i++ {
			scanner.Scan()
			line := scanner.Text()
			plans[planIdx][i] = make([]int, m)
			for j := 0; j < m; j++ {
				plans[planIdx][i][j] = int(line[j] - '0')
			}
		}
	}
	
	// Try all possible combinations of plans
	minPlans := q + 1
	var bestSolution []int
	
	// Try all possible combinations using bitmask
	for mask := 0; mask < (1 << q); mask++ {
		// Create a combined plan
		combined := make([][]int, n)
		for i := 0; i < n; i++ {
			combined[i] = make([]int, m)
		}
		
		// Apply selected plans
		selectedPlans := make([]int, 0)
		for i := 0; i < q; i++ {
			if (mask & (1 << i)) != 0 {
				selectedPlans = append(selectedPlans, i+1)
				for row := 0; row < n; row++ {
					for col := 0; col < m; col++ {
						if plans[i][row][col] == 1 {
							combined[row][col] = 1
						}
					}
				}
			}
		}
		
		// Check if this combination satisfies the requirements
		valid := true
		for i := 0; i < n; i++ {
			for j := 0; j < m; j++ {
				if initialState[i][j] == 1 && combined[i][j] == 1 {
					valid = false
					break
				}
				if initialState[i][j] == 0 && combined[i][j] == 0 {
					valid = false
					break
				}
			}
			if !valid {
				break
			}
		}
		
		if valid && len(selectedPlans) < minPlans {
			minPlans = len(selectedPlans)
			bestSolution = selectedPlans
		}
	}
	
	if minPlans == q+1 {
		fmt.Println(-1)
		return
	}
	
	fmt.Println(minPlans)
	for _, plan := range bestSolution {
		fmt.Printf("%d ", plan)
	}
	fmt.Println()
} 

发表于 2025-03-23 15:13:46 回复(0)
#include <array>
#include <bitset>
#include <iostream>
#include <type_traits>
using namespace std;

int main() {
    int n, m, q;
    cin >> n >> m >> q;
    bitset<49> map;
    array<bitset<49>, 7> covers;
    string s, t;
    for (int i = 0; i < n; ++i) {
        cin >> t;
        s += t;
    }
    map = bitset<49>(s);

    for (int i = 0; i < q; ++i) {
        s.clear();
        for (int j = 0; j < n; ++j)
            cin >> t, s += t;
        covers[i] = bitset<49>(s);
    }

    int count = q + 1, ans;
    // 遍历所有可能的cover
    for (int i = 0; i <= 1 << q; ++i) {
        // 如果方案数变多,则直接跳过
        if (__builtin_popcount(i) >= count)
            continue;

        // 将其初始化为全0
        bitset<49> out;
        // 从前向后cover
        for (int j = 0; j < q; ++j) {
            if (i >> j & 1)
                out |= covers[j];
        }
        // 判断是否满足条件
        if ((map | out) == (1LL << m * n) - 1 && (map & out) == 0) {
            count = __builtin_popcount(i);
            ans = i;
        }
    }

    if (count == q + 1)
        count = -1;
    cout << count << endl;
    if (count != -1) {
        for (int i = 0; i < q; ++i)
            if (ans >> i & 1)
                cout << i + 1 << ' ';
    }
}
发表于 2025-03-03 21:54:53 回复(0)
我题目都没懂
发表于 今天 18:53:28 回复(0)
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;

using vvb = vector<vector<bool>>;

vvb add_plan(vvb& plan, vvb& fire) {
    int n = plan.size();
    int m = plan[0].size();
    vvb new_fire(n, vector<bool>(m, false));
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            //当某个格子至少放置一个烟花时,这个格子视为燃放烟花
            new_fire[i][j] = plan[i][j] || fire[i][j];
        }
    }
    return new_fire;
}

vector<vector<int>>paths;//可能的烟花放置方案
bool choose_plan(vector<vvb>& plans, int i, vvb& grass, vvb fire,
                 vector<int>path) {
    if (fire == grass){
        paths.push_back(path);
        return true;
    }//如果可以放烟花的地方完全放烟花,禁止放烟花的地方未放烟花,条件成立

    if (i == plans.size())return false;
    vvb new_fire = add_plan(plans[i], fire);
    //递归,每个方案都有选择或不选择两种可能
    bool not_choose = choose_plan(plans, i + 1, grass, fire, path);
    path.push_back(i);//如果计划选择,记录选择的计划
    bool choose = choose_plan(plans, i + 1, grass, new_fire, path);
    return choose || not_choose;
}

void find(vvb& mat) {
    for (const auto& vec : mat) {
        for (const auto& i : vec) {
            cout << i << ' ';
        }
        cout << endl;
    }
}//验证函数,用于帮助查找错误

int main() {
    int n, m, q;
    cin >> n >> m >> q;
    vvb grass(n, vector<bool>(m, false));//草地
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            char c;
            cin >> c;
            //如果草地有杂物,那么禁止燃放烟花,即没有杂物的草地可以放烟花
            if (c == '0')grass[i][j] = true;
            else grass[i][j] = false;
        }
    }
    //find(grass);
    vector<vvb>plans;//计划
    for (int i = 0; i < q; i++) {
        vvb vec(n, vector<bool>(m, false));
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                char c;
                cin >> c;
                if (c == '0')vec[i][j] = false;
                else vec[i][j] = true;
            }
        }
        //find(vec);
        plans.push_back(vec);
    }
    vvb fire(n, vector<bool>(m, false));//选择一些计划后实际烟花放置情况
    //find(plans[0]);
    vector<int>path;//选择的计划编号
    if (choose_plan(plans, 0, grass, fire, path)) {
        int lest=q;
        for(const auto& vec:paths){
            //找到可行的最小计划数
            lest=lest<vec.size()?lest:vec.size();
        }
        for(const auto& vec:paths){
            if(vec.size()==lest){
                //任选一个所需计划最小的方案输出
                cout<<lest<<endl;
                for(const auto& i:vec){
                    cout<<i+1<<' ';
                }
                break;
            }
        }
    }
    else{
        cout<<-1;
    }
}
// 64 位输出请用 printf("%lld")
发表于 2026-02-27 21:13:50 回复(0)
咋难题没人讨论呢
发表于 2026-02-26 15:24:37 回复(0)
import sys
n,m,q=map(int,input().split())
org_square=[]
plan=[[]for _ in range(q)]
for i in range(n):
    org_square+=list(map(str,input()))
for i in range(q):
    for j in range(n):
        plan[i]+=list(map(str,input()))
space_idx=[index for index,char in enumerate(org_square) if char=='0']
fw_idx=[[index for index,char in enumerate(num) if char=='1'] for num in plan]
for p in fw_idx:
    if set(p)==set(space_idx):
        print("1")
        print(fw_idx.index(p)+1)
        sys.exit()
comb_list,idx_list=[[]],[[]]
for p in fw_idx:
    comb_list+=[curr+p for curr in comb_list]
    idx_list+=[curr+[fw_idx.index(p)+1] for curr in idx_list]
for comb in comb_list:
    if set(comb)== set(space_idx):
        print(len(idx_list[comb_list.index(comb)]))
        print(' '.join(list(map(str,idx_list[comb_list.index(comb)]))))
        sys.exit()
print("-1")



经自行验证,没有通过的示例也都是符合要求的,加几个限制条件说不定可以全通过
发表于 2025-12-16 22:52:01 回复(0)
笑死了,有两个测试用例的结果都是找不到方案,结果一个预期输出要求是 -1,另一个预期输出要求是 0,这让我怎么搞?

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)

发表于 2025-12-01 23:42:41 回复(0)
What can i say?man ba, out !
发表于 2025-11-29 16:01:30 回复(0)
这道题是简单?瓦特发?
发表于 2025-10-13 13:41:57 回复(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;
    }
}


发表于 2025-10-09 15:19:43 回复(0)
这是简单题???
发表于 2025-09-19 17:50:47 回复(0)
这个输出不应该是-1吗?为什么会出现0这个结果啊?
发表于 2025-08-25 22:32:01 回复(0)
没找到最小数量,只过了60%的用例,这题真的是简单难度?
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);


    }
}


发表于 2025-08-13 23:24:12 回复(0)
不知道示例2明明有5种方案,但答案是4种,并且自己也说有两种解法,及1,2,3,4或1,2,3,5,但就是不合并成5种方法,及1,2,3,4,5,导致我的代码明明可以求出所有方案,但就是过不了用例0。
#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]<<" ";
    }
}


发表于 2025-08-12 23:36:58 回复(1)
我写的可能有冗余,关键是没想到这烟花会有初始计划直接干草垛和一个坑多个烟花的情况
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;
    }
}

发表于 2025-08-08 20:48:02 回复(0)