Google-APAC2015-"Seven-segment display"

本文介绍了一种通过BruteForce方法解决七段显示器状态解析问题的算法。利用1280种状态组合来确定下一状态,若结果唯一则输出该状态,否则返回ERROR。文章详细解释了解题思路、算法实现及代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原题:seven-segment display

=================================

#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”的组合,所以我们不需要管这些状态组合是什么,只要显示是一样的,输出就可以了。

=================================

#3 数据结构
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();
	}
}


评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值