=================================
#1 理解题目
比如test case的输入为:
1 1111111
2 0000000 0001010
3 0100000 0000111 0000011
5 1011011 1011111 1010000 1011111 1011011
每一行是一组LED的显示,每一行第一个数字表示LED的状态数目,接下来是LED每根二极管的ON / OFF状态。
上面的test case的输出为:
Case #1: 1110000
Case #2: ERROR!
Case #3: 0100011
Case #4: 0010011
这些输出表明第1,3,4都可以明确知道下一个LED的输出,但是第2个test case没有办法确定唯一的输出,因此“ ERROR! ”。
=================================
#2 算法
最初我尝试使用“逻辑”去解这道题目,比方说,如果状态数目有至少10个,那么可以取前10个状态,因为10个状态已经遍历了每一根二极管了,把10个状态AND起来就可以知道哪一些二极管是好,哪一些二极管是坏了。但是如果少于10个状态又该怎么办呢?
Parker大神指出:无须从“逻辑”上去解决这道题目,使用Brute Force就可以了。这里总共7个二极管,每个有好坏(0/1)两种状态,总共是2^7=128种情况。算上开始的数字(0~9),总共需要枚举128 * 10 = 1280种状态。
比如假设显示器的状态是:0110111,开始状态是1111011(就是9),那么两个状态相AND得到的0110011,如果与显示的状态一样,那么假设可以继续进行,如果不一样就排除这种“显示器+开始数字”的组合。哪怕最后显示一样,一种可能是“显示器i+开始数字j”的组合,另外一种可能是“显示器m+开始数字n”的组合,所以我们不需要管这些状态组合是什么,只要显示是一样的,输出就可以了。
=================================
LED的状态可以直接用0-127的int来表示,而0~9作为初始状态可以先hash到对应的字符串显示,然后从字符串再hash到integer(比如:0 --> "1111110" --> 126)。
=================================
#4 代码
import java.io.*;
import java.util.*;
class Solution {
// global variable
public static HashMap<Integer, Integer> ledIntMap = new HashMap<Integer, Integer>();
public static void main(String[] args) {
File inFile = new File("A-large-practice.in");
File outFile = new File("A-large-practice.out");
try {
BufferedReader br = new BufferedReader(new FileReader(inFile));
BufferedWriter bw = new BufferedWriter(new FileWriter(outFile));
int T = Integer.parseInt(br.readLine());
init();
for (int i = 1; i <= T; i++) {
String s = br.readLine();
bw.write("Case #" + i + ": " + solve(s) + "\n");
}
bw.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/* display the next state according to previous states */
public static String solve (String s) {
String[] parts = s.split("\\s");
int N = Integer.parseInt(parts[0]);
int next = -1; // next state should be unique and valid from 0 to 127
for (int i = 0; i < 128; i++) {
for (int j = 0; j < 10; j++) {
int curr = j; // current state & init state
int k;
for (k = 1; k <= N; k++) {
// System.out.println(curr);
int disp = i & ledIntMap.get(curr); // display the current state
if (disp != strToInt(parts[k])) break; // not a valid led & init num combination
curr--;
if (curr < 0) curr = 9;
}
if (k == N+1) {
int disp = i & ledIntMap.get(curr); // display the final state
if (next == -1) next = disp;
else if (next != disp) return "ERROR!";
}
}
}
return intToStr(next);
}
/* initialization */
public static void init() {
// hash the number to the LED states
HashMap<Integer, String> intLedMap = new HashMap<Integer, String>();
intLedMap.put(0, "1111110");
intLedMap.put(1, "0110000");
intLedMap.put(2, "1101101");
intLedMap.put(3, "1111001");
intLedMap.put(4, "0110011");
intLedMap.put(5, "1011011");
intLedMap.put(6, "1011111");
intLedMap.put(7, "1110000");
intLedMap.put(8, "1111111");
intLedMap.put(9, "1111011");
// hash the LED states into a binary number
for (int i = 0; i <= 9; i++) {
String led = intLedMap.get(i);
ledIntMap.put(i, strToInt(led));
}
}
/* convert the string into a integer */
public static int strToInt(String s) {
int num = 0;
int base = 1;
for (int i = s.length()-1; i >=0; i--) {
int bit = s.charAt(i) == '1' ? 1 : 0;
num += bit * base;
base *= 2;
}
return num;
}
/* convert the integer into a string */
public static String intToStr(int num) {
StringBuilder builder = new StringBuilder();
while (num != 0) {
builder.insert(0, num % 2 == 1 ? "1" : "0");
num /= 2;
}
while (builder.length() < 7) builder.insert(0, "0");
return builder.toString();
}
}