1,电子数字
题目:
电子数字 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 电子数字在生活中很常见,而许多的电子数字是由LED数码管制作而成。数字LED数码管一般由7个发光二极管封装在一起,组成'8'字型,引线在内部连接完成。如下图所示,我们可以对每个发光管进行编码从1到7。而数字0到数字9可以由这七根发光管的亮暗来表示。 digit8.jpg 对LED数码管的二极管进行编码 digit.jpg 用LED数码管表示数字0-9 假设我们现在有从左到右排列好的K个LED数码管,并且我们已知每个数码管当前有哪些编号的二极管是亮着的,另外剩余的二极管由于某些原因,我们并不清楚它们的亮暗情况。由于已经有部分二极管是确定亮着的,所以每个LED数码管能表示的数字范围会有所缩小,譬如假设1号二极管已经确定是亮着的状态,那么这个LED数码管就不能表示数字1和4。 我们想知道的是,给定一个数N,在这K个LED数码管的当前亮暗的状态下,所有可能表示的数中,比N小的数有多少个。 注意,前导0是必须的,假设有4个数码管的话,'0000'表示0,'0123'表示123,即每个数的表示方法唯一。 输入 每个输入数据包含多个测试点。 第一行为测试点的个数 S ≤ 100。之后是 S 个测试点的数据。测试点之间无空行。 每个测试点的第一行为 K(1 ≤ K ≤ 5)和N(0 ≤ N ≤ 109)。之后是K行,每行表示对应数码管已点亮的二极管的情况。每行至少包含一个数字,表示对应点亮的二极管的编号,即每个数码管至少有一根二极管是点亮的。二极管编号的范围保证在1到7之间,且每行无重复编号。 注意表示数码管点亮情况的每行数字之间以及行首行末之间可能存在冗余空格,每行的字符总长度不超过100。 输出 对于每个测试点,对应的结果输出一行,表示这K个数码管在当前状态下,所有可能表示的数中,比N小的数有多少个。 样例解释 第一个样例中,只有'020', '026', '028'符合要求。 第三个样例中,只有'000'符合要求。 样例输入 3 3 50 3 1 1 4 5 1 5 6 7 4 100 1 2 3 4 5 6 7 1 1 7 样例输出 3 0 1
答案:
import java.util.Scanner; import java.util.ArrayList; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); String s1 = in.nextLine(); String[] a1 = s1.split(" "); int S = Integer.parseInt(a1[0]); while (S-- > 0) { s1 = in.nextLine(); a1 = s1.split(" "); int K = Integer.parseInt(a1[0]); int N = Integer.parseInt(a1[1]); ArrayList<ArrayList<Integer>> light = new ArrayList(); while (K-- > 0) { ArrayList<Integer> temp = new ArrayList(); String str = in.nextLine(); String[] a = str.split(" "); for (String s : a) { if (s.length() != 0) { temp.add(Integer.parseInt(s)); } } light.add(temp); } ArrayList<ArrayList<Integer>> value = new ArrayList(); for (ArrayList<Integer> list : light) { value.add(getValue(list)); } ArrayList<Integer> ans = new ArrayList(); boolean flag = true; for (ArrayList<Integer> va : value) { if (flag) { for (int n : va) { ans.add(n); } flag = false; } else { ArrayList<Integer> tempAns = new ArrayList(); for (int n : va) { for (int an : ans) { tempAns.add(an * 10 + n); } } ans = new ArrayList(tempAns); } } int num = 0; for (int n : ans) { if (n < N) { num++; } } System.out.println(num); } } public static ArrayList<Integer> getValue(ArrayList<Integer> list) { ArrayList<Integer> result = new ArrayList(); for (int i = 0; i <= 9; i++) { result.add(i); } if (list.contains(1)) { result.remove((Integer)1); result.remove((Integer)4); } if (list.contains(2)) { result.remove((Integer)1); result.remove((Integer)2); result.remove((Integer)3); result.remove((Integer)7); } if (list.contains(3)) { result.remove((Integer)5); result.remove((Integer)6); } if (list.contains(4)) { result.remove((Integer)1); result.remove((Integer)7); result.remove((Integer)0); } if (list.contains(5)) { result.remove((Integer)1); result.remove((Integer)3); result.remove((Integer)4); result.remove((Integer)5); result.remove((Integer)7); result.remove((Integer)9); } if (list.contains(6)) { result.remove((Integer)2); } if (list.contains(7)) { result.remove((Integer)1); result.remove((Integer)4); result.remove((Integer)7); } return result; } }
2,源代码编译
源代码编译 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在网易游戏的日常工作中,C++ 是一门常用的语言。面对众多的 C++ 代码,等待源文件编译的漫长时间是个令人糟心的时刻,一直以来大家对此怨声载道。终于有一天,大家找到了你,一位优秀的程序员,请你来帮忙分析一下编译速度的瓶颈。 经过一番调查和研究,你发现一些源代码之间是有依赖关系的。例如,某个源文件 a.cpp 编译链接生成了动态链接库 a.dll,而 b.cpp 编译链接生成的 b.dll 依赖于 a.dll。这个时候,必须等待 a.dll 生成之后才能生成 b.dll。为了表达简单,我们这个时候称 b.cpp 依赖于 a.cpp。 网易游戏内部使用了一个分布式并行的编译平台,可以同时编译多个不互相依赖的文件,大大提高了源代码的编译速度。然而当某些依赖链很长的时候,这个编译平台也无能为力,只能按照依赖顺序一个一个完成编译,从而造成了很长的编译时间。 为了验证这个想法,你决定着手通过代码分析这些文件之间的编译顺序。已知这些文件的文件名,以及这些文件所依赖的其他文件,你需要编写一个程序,输出一个可行的编译所有源文件的编译顺序。如果有多种可行的序列,请输出所有文件名序列中字典序最小的那一个(序列 (a1, a2, ..., an) 字典序小于序列 (b1, b2, ..., bn),当且仅当存在某个 i ,使得 ai 的字典序小于 bi,并且对于任意 j < i ,都有 aj = bj)。 输入 输入包含多组测试数据。 输入的第一行包含一个整数 T(T ≤ 100),表示输入中一共包含有 T 组测试数据。 每组测试数据第一行是一个整数 N(N ≤ 1000),表示一共有 N 个源代码文件。随后一共有 N 行数据,其中第 i(0 ≤ i < N) 行数据包含序号为 i 的源代码文件的依赖信息。每一行开头是一个字符串,表示这一个文件的文件名,随后一个整数 m(0 ≤ m ≤ N),表示编译这个源文件之前需要先编译 m 个依赖文件。之后是 m 个整数 j0 ... jm-1,表示这 m 个依赖文件的序号(0 ≤ j < N) 。所有的文件名仅由小写字母、数字或“.”组成,并且不会超过 10 个字符。保证 n 个源代码文件的文件名互不相同。 输出 对于每一组输入,按照编译先后顺序输出一组可行的编译顺序,一行一个文件名。如果有多种可行的序列,请输出所有文件名序列中字典序最小的那一个。如果不存在可行的编译顺序,输出一行 ERROR。每组测试数据末尾输出一个空行。 样例输入 3 2 a.cpp 0 b.cpp 1 0 2 cb 0 c 0 2 a.cpp 1 1 b.cpp 1 0 样例输出 a.cpp b.cpp c cb ERROR
答案:
import java.util.ArrayList; import java.util.Map; import java.util.Scanner; import java.util.TreeMap; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); int T = in.nextInt(); while (T-- > 0) { Map<String, ArrayList<Integer>> map = new TreeMap(); int N = in.nextInt(); while (N-- > 0) { String cpp = in.next(); int m = in.nextInt(); ArrayList<Integer> list = new ArrayList(); while (m-- > 0) { int n = in.nextInt(); list.add(n); } map.put(cpp, list); } ArrayList<String> list = new ArrayList(); for (String str : map.keySet()) { list.add(str); } Map<String, ArrayList<String>> map2 = new TreeMap(); for (String str : map.keySet()) { ArrayList<String> listStr = new ArrayList(); ArrayList<Integer> temp = map.get(str); for (int n : temp) { listStr.add(list.get(n)); } map2.put(str, listStr); } ArrayList<String> result = new ArrayList(); int size = map2.size(); int n = size; while (n > 0) { for (String str : map2.keySet()) { String temp = str; if (map2.get(str).size() == 0 || result.containsAll(map2.get(str))) { if (!result.contains(str)) { result.add(str); n--; } } } if (size == n) { System.out.println("ERROR"); break; } } for (String str : result) { System.out.println(str); } System.out.println(); } } }
3, 画线
题目:
画线 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小王最近在开发一种新的游戏引擎,但是最近遇到了性能瓶颈。于是他打算从最基本的画线功能开始分析优化。画线其实就是调用一次drawline命令,根据给出的两端坐标,在屏幕画出对应的线段。但是小王发现,很多的drawline其实可以合并在一起,譬如下图中的线段(2,3)-(4,5)和线段(3,4)-(6,7),其实可以合并为一次drawline命令,直接画出线段(2,3)-(6,7)。当然有些线段是无法合并的,如线段(-3,8)-(1,8)和线段(3,8)-(6,8),就必须调用两次drawline命令。 coordinate.jpg 画线示意图。注意颜色只是用于区分,实际线段都是黑色 给出N条drawline指令以及对应的线段坐标,小王想知道,实际最少用多少次drawline指令就可以画出来。 小王想先从最简单的情况开始分析优化,所以线段只包含四种情况:水平线段,垂直线段以及正反45度的线段。 输入 每个输入数据包含多个测试点。 第一行为测试点的个数 S ≤ 10。之后是 S 个测试点的数据。 每个测试点的第一行为 N(N ≤ 105)。之后是 N 行,每行包含4个整数:x0, y0, x1, y1,表示线段(x0,y0)-(x1,y1),坐标的范围在[-108, 108],保证线段的长度大于0。 输出 对于每个测试点,对应的结果输出一行,表示最少用多少次指令即可完成所有的画线。 样例输入 2 4 3 8 6 8 -3 8 1 8 2 3 4 5 3 4 6 7 5 1 1 2 2 2 2 3 3 3 3 4 2 4 2 5 1 1 0 100 0 样例输出 3 3
答案:
import java.util.ArrayList; import java.util.Scanner; import java.util.TreeMap; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); int S = in.nextInt(); while (S-- > 0) { int N = in.nextInt(); ArrayList<int[]> line1= new ArrayList(); ArrayList<int[]> line2= new ArrayList(); ArrayList<int[]> line3= new ArrayList(); ArrayList<int[]> line4= new ArrayList(); while (N-- > 0) { int[] index = new int[4]; for (int i = 0; i < 4; i++) { index[i] = in.nextInt(); } if (index[1] == index[3]) { line1.add(index); } else if (index[0] == index[2]) { line2.add(index); } else { if ((index[3] - index[1]) / (index[2] - index[0]) == 1) { line3.add(index); } else { line4.add(index); } } } int result = 0; int size = 0; while (line1.size() != size) { int[] temp = line1.get(0); TreeMap<Integer, Integer> tree= new TreeMap(); for (int i = 0; i < line1.size(); i++) { if (line1.get(i)[1] == temp[1]) { size++; if (tree.containsKey(line1.get(i)[1])) { int max = Math.max(tree.get(line1.get(i)[1]), line1.get(i)[2]); tree.put(line1.get(i)[0], max); } else { tree.put(line1.get(i)[0], line1.get(i)[2]); } } } int[] range = new int[2]; for (int n : tree.keySet()) { result++; if (range[0] == 0 && range[1] == 0) { range[0] = n; range[1] = tree.get(n); continue; } if (n <= range[1]) { result--; range[1] = Math.max(range[1], tree.get(n)); } else { range[0] = n; range[1] = tree.get(n); } } } // System.out.println(result); //line2 size = 0;; while (line2.size() != size) { int[] temp = line2.get(0); TreeMap<Integer, Integer> tree= new TreeMap(); for (int i = 0; i < line2.size(); i++) { if (line2.get(i)[0] == temp[0]) { size++; if (tree.containsKey(line2.get(i)[0])) { int max = Math.max((int)tree.get(line2.get(i)[0]), line2.get(i)[1]); tree.put(line2.get(i)[1], max); } else { tree.put(line2.get(i)[1], line2.get(i)[3]); } } } int[] range = new int[2]; for (int n : tree.keySet()) { result++; if (range[0] == 0 && range[1] == 0) { range[0] = n; range[1] = tree.get(n); continue; } if (n <= range[1]) { result--; range[1] = Math.max(range[1], tree.get(n)); } else { range[0] = n; range[1] = tree.get(n); } } } // System.out.println(result); //line3 size = 0; while (line3.size() != size) { int[] temp = line3.get(0); int slope = temp[1] - temp[0]; TreeMap<Integer, Integer> tree= new TreeMap(); for (int i = 0; i < line3.size(); i++) { if (line3.get(i)[1] - line3.get(i)[0] == slope) { size++; if (tree.containsKey(line3.get(i)[0])) { int max = Math.max(tree.get(line3.get(i)[0]), line3.get(i)[2]); tree.put(line3.get(i)[0], max); } else { tree.put(line3.get(i)[0], line3.get(i)[2]); } } } int[] range = new int[2]; for (int n : tree.keySet()) { result++; if (range[0] == 0 && range[1] == 0) { range[0] = n; range[1] = tree.get(n); continue; } if (n <= range[1]) { result--; range[1] = Math.max(range[1], tree.get(n)); } else { range[0] = n; range[1] = tree.get(n); } } } // System.out.println(result); //line4() size = 0; while (line4.size() != size) { int[] temp = line4.get(0); int slope = temp[1] + temp[0]; TreeMap<Integer, Integer> tree= new TreeMap(); for (int i = 0; i < line4.size(); i++) { if (line4.get(i)[1] + line4.get(i)[0] == slope) { size++; if (tree.containsKey(line4.get(i)[0])) { int max = Math.max(tree.get(line4.get(i)[0]), line4.get(i)[2]); tree.put(line4.get(i)[0], max); } else { tree.put(line4.get(i)[0], line4.get(i)[2]); } } } int[] range = new int[2]; for (int n : tree.keySet()) { result++; if (range[0] == 0 && range[1] == 0) { range[0] = n; range[1] = tree.get(n); continue; } if (n <= range[1]) { result--; range[1] = Math.max(range[1], tree.get(n)); } else { range[0] = n; range[1] = tree.get(n); } } } System.out.println(result); } } }