AcWing 95. 费解的开关

Problem: AcWing 95. 费解的开关

文章目录

  • 思路
  • 解题方法
  • 复杂度
  • Code

思路

这是一个经典的搜索问题。我们需要找到最少的步骤来使所有的灯都亮起来。每一步我们可以选择一个灯进行切换,切换后该灯以及其上下左右的灯都会改变状态。我们可以通过枚举第一行的所有状态,然后根据当前行的状态来决定下一行的操作,最后检查最后一行是否全部点亮。

解题方法

我们可以使用深度优先搜索(DFS)来解决这个问题。首先,我们枚举第一行的所有状态,然后对每一种状态进行深度优先搜索。在搜索过程中,我们根据当前行的状态来决定下一行的操作。如果当前行的某个灯是关闭的,我们就需要在下一行的对应位置进行切换操作。最后,我们检查最后一行是否全部点亮,如果全部点亮,我们就更新最小步骤数。

复杂度

时间复杂度:

O ( 2 n ) O(2^n) O(2n),其中n是灯的数量。因为我们需要枚举第一行的所有状态,所以时间复杂度是2的n次方。

空间复杂度:

O ( n ) O(n) O(n),其中n是灯的数量。我们需要使用一个二维数组来存储灯的状态,所以空间复杂度是O(n)。

Code

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;

public class Main {
	static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
	static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
	static StreamTokenizer sr = new StreamTokenizer(in);
	static int N = 5;
	static int n;
	static char[][] g = new char[N][N];
	static char[][] backup = new char[N][N];
	static int[] dx = { 0, -1, 0, 1, 0 };
	static int[] dy = { 0, 0, 1, 0, -1 };

	public static void main(String[] args) throws IOException {
		n = Integer.parseInt(in.readLine());
		while (n-- > 0) {
			for (int i = 0; i < N; i++) {
				g[i] = in.readLine().toCharArray();
			}
			// 首先枚举第一行的所有情况
			out.println(dfs());
			if (n > 0)
				in.readLine();
		}
		out.flush();
	}

	public static int dfs() {
		int res = Integer.MAX_VALUE; // 初始化最小步骤数为最大值
		for (int k = 0; k < 1 << N; k++) {
			// 使用clone备份游戏状态
			for (int i = 0; i < N; i++) {
				backup[i] = g[i].clone();
			}

			int step = 0;
			// 对第一行执行翻转操作
			for (int i = 0; i < N; i++) {
				if ((k >> i & 1) == 0) {
					step++;
					turn(0, i);
				}
			}

			// 根据当前行的状态决定下一行的翻转操作
			for (int i = 0; i < N - 1; i++) {
				for (int j = 0; j < N; j++) {
					if (g[i][j] == '0') {
						step++;
						turn(i + 1, j);
					}
				}
			}

			// 检查最后一行是否全部点亮
			boolean flag = true;
			for (int j = 0; j < N; j++) {
				if (g[N - 1][j] == '0') {
					flag = false;
					break;
				}
			}

			// 更新最小步骤数
			if (flag)
				res = Math.min(res, step);

			// 恢复游戏状态
			for (int i = 0; i < N; i++) {
				g[i] = backup[i].clone();
			}
		}

		// 如果最小步骤数大于6,返回-1,否则返回最小步骤数
		return res <= 6 ? res : -1;
	}

	private static void turn(int x, int y) {
		for (int i = 0; i < 5; i++) { // 注意这里改为5,与dx和dy的长度一致
			int a = x + dx[i];
			int b = y + dy[i];
			if (a < 0 || a >= N || b < 0 || b >= N)
				continue;
			g[a][b] ^= 1;
		}
	}

}

你可能感兴趣的:(刷题,acwing,dfs)