2016網易遊戲實習算法題解(今年找暑期實習的時候參加的)

1,電子數字java

題目:git

電子數字 時間限制: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
View Code

答案:程序員

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; } }
View Code

 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
View Code

答案:ide

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(); } } }
View Code

 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
View Code

答案:優化

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); } } }
View Code
相關文章
相關標籤/搜索