- 题目
实现及思路
import java.util.Scanner;
//因为每个灯只有0/1两种情况,所以每行可用一个6位二进制数表示 btye8位
//若枚举所有开关,则有2^30种情况
//若第一行开关确定,则第一行灯的情况由第二行开关决定,且只有一种情况使第一行灯全灭
//同理,要使第二行灯全灭,第三行开关只有一种情况
//所以只需要枚举第一行开关情况即可确定最终情况
public class cs {
byte[] light = new byte[5];// 灯
byte[] shift = new byte[5];// 变化中的灯
byte[] off = new byte[5];// 开关
int n;
void io() {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
for (int i = 1; i <= n; i++) {
for (int j = 0; j < 5; j++) {
for (int k = 0; k < 6; k++) {
int x = sc.nextInt();
light[j] = set(light[j], k, x);
}
}
for (byte n = 0; n < 64; n++) {
byte offs = n;// 枚举第一行开关的情况,00000~111111
shift = light.clone();
for (int m = 0; m < 5; m++) {
off[m] = offs;
for (int s = 0; s < 6; s++) {
if (get(offs, s) == 1) {
shift[m] = file(shift[m], s);
if (s > 0)
shift[m] = file(shift[m], s - 1);
if (s < 5)
shift[m] = file(shift[m], s + 1);
}
}
//次行灯的情况等于和该行开关的异或
//0^0=0 0^1=1 1^0=1 1^1=0
if (m < 4)
shift[m + 1] ^= offs;
//下一行的开关由该行的灯决定,要使该行全灭,则开关应与灯一致
offs = shift[m];
}
if (shift[4] == 0) {
out(off, i);
break;
}
}
}
}
//输出格式
private void out(byte[] off, int n) {
System.out.println("PUZZLE#" + n);
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 6; ++j) {
System.out.print(get(off[i], j));
if (i < 5)
System.out.print(" "); // 每个数之间有空格
}
System.out.println();
}
}
private byte set(byte b, int k, int x) {
// 将b的k位设置为x
//b=101010 k=4/1 x=1/0
// 101010 101010
// | 010000 & 111101
// = 111010 = 101000
if (x == 0)
b &= ~(1 << k);
else
b |= (1 << k);
return b;
}
private int get(byte b, int k) {
// 获取b的k位
return (b >> k) & 1;
}
private byte file(byte b, int k) {
// 使b的k位取反
b ^= (1 << k);
return b;
}
//主函数
public static void main(String[] args) {
cs a = new cs();
a.io();
}
}
测试用例及结果