第一行输入三个整数
代表草地的长、草地的宽、计划数量。
此后
行,每行输入
个字符,代表草地初始状态。
此后
行,每行输入
个字符,用于描述计划。
全部字符仅为数字
或
。
如果不存在满足要求的燃放方案,直接输出
。
否则,请按如下格式输出:
第一行上输出一个整数
代表使用到的计划数量。
第二行输出
个整数代表你所选择的计划编号。编号即输入顺序,从
开始计数。
如果存在多个解决方案,您可以输出任意一个,系统会自动判定是否正确。注意,自测运行功能可能因此返回错误结果,请自行检查答案正确性。
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 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;
}
} 卡在第20个测试用例了
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
private static int min = Integer.MAX_VALUE;
private static List res = new ArrayList();
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int m = in.nextInt();
int q = in.nextInt();
int[][] grid = new int[n][m];
int[][] grid1 = new int[n][m];
List plain = new ArrayList();
long empty = 0;
for (int i = 0; i < n; i++) {
String row = in.next();
for (int j = 0; j < row.length(); j++) {
grid[i][j] = row.charAt(j) - '0';
grid1[i][j] = row.charAt(j) - '0';
if (grid[i][j] == 0) {
empty |= 1L << (i * m + j);
}
}
}
for (int k = 0; k < q; k++) {
int[][] g = new int[n][m];
for (int i = 0; i < n; i++) {
String row = in.next();
for (int j = 0; j < row.length(); j++) {
g[i][j] = row.charAt(j) - '0';
}
}
plain.add(g);
}
dfs(0, plain, grid, grid1, empty, 0, new ArrayList());
int size = res.size();
if (size == 0) {
System.out.println(-1);
} else {
System.out.println(size);
for (int i = 0; i < size; i++) {
System.out.print(res.get(i));
if (i != size - 1) {
System.out.print(" ");
}
}
}
}
public static Object[] add(int[][] grid, int[][] grid1, int[][] plain, long empty) {
int m = grid.length;
int[][] newGrid = new int[m][grid[0].length];
for (int i = 0; i < m; i++) {
newGrid[i] = Arrays.copyOf(grid[i], grid[i].length);
for (int j = 0; j < grid[i].length; j++) {
if (grid1[i][j] == 1 && plain[i][j] == 1) {
return new Object[]{false, 0L, null};
}
if (newGrid[i][j] == 0 && plain[i][j] == 1) {
empty |= 1L << (i * m + j);
newGrid[i][j]++;
}
}
}
return new Object[]{true, empty, newGrid};
}
private static void dfs(int i, List plain, int[][] grid, int[][] grid1, long empty, long currEmpty,
List path) {
if (i == plain.size()) {
if (currEmpty == empty) {
if (path.size() < min) {
min = path.size();
res = new ArrayList(path);
}
}
return;
}
Object[] ob = add(grid, grid1, plain.get(i), currEmpty);
boolean valid = (boolean) ob[0];
dfs(i + 1, plain, grid, grid1, empty, currEmpty, path);
if (valid) {
long newEmpty = (long) ob[1];
int[][] newGrid = (int[][]) ob[2];
path.add(i + 1);
dfs(i + 1, plain, newGrid, grid1, empty, newEmpty, path);
path.remove(path.size() - 1);
}
}
}这全是障碍物,也没法种啊
2 2 5 11 11 10 00 01 00 11 11 00 10 00 01
//HJ95 小心火烛的歪
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
//草地的长、草地的宽、计划数量
String[] nums = in.nextLine().split(" ");
int n = Integer.parseInt(nums[0]);
int m = Integer.parseInt(nums[1]);
int q = Integer.parseInt(nums[2]);
//草坪:单个n*m
char[][] grass = new char[n][m];
//初始化草坪
for (int i = 0; i < n; i++) {
char[] line = in.nextLine().toCharArray();
for (int j = 0; j < m; j++) {
grass[i][j] = line[j];
}
}
//满足的计划编号
List<String> res = new ArrayList<>();
//从1开始计数
for (int k = 1; k <= q; k++) {
//该计划是否满足
boolean flag = true;
for (int i = 0; i < n; i++) {
char[] line = in.nextLine().toCharArray();
for (int j = 0; j < m; j++) {
//有杂物就不能放,没有杂物可放可不放
if (grass[i][j] == '1' && line[j] == '1') {
flag = false;
break;
}
}
}
//否则就是满足的
if (flag) {
res.add(k + "");
}
}
//输出
System.out.println(res.size());
System.out.println(String.join(" ", res));
}