日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

2020年 第11届 蓝桥杯 第2次模拟赛真题详解及小结【Java版】

發(fā)布時(shí)間:2024/9/30 java 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 2020年 第11届 蓝桥杯 第2次模拟赛真题详解及小结【Java版】 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
  • 藍(lán)橋杯 Java B組 省賽真題詳解及小結(jié)匯總【2013年(第4屆)~2020年(第11屆)】

  • 注意:部分代碼及程序 源自 藍(lán)橋杯 官網(wǎng)視頻(歷年真題解析)?鄭未老師。
  • 2013年 第04屆 藍(lán)橋杯 Java B組 省賽真題詳解及小結(jié)
  • 2014年 第05屆 藍(lán)橋杯 Java B組 省賽真題詳解及小結(jié)
  • 2015年 第06屆 藍(lán)橋杯 Java B組 省賽真題詳解及小結(jié)
  • 2016年 第07屆 藍(lán)橋杯 Java B組 省賽真題詳解及小結(jié)
  • 2017年 第08屆 藍(lán)橋杯 Java B組 省賽真題詳解及小結(jié)
  • 2018年 第09屆 藍(lán)橋杯 Java B組 省賽真題詳解及小結(jié)
  • 2019年?第10屆 藍(lán)橋杯 Java B組 省賽真題詳解及小結(jié)
  • 2020年?第11屆 藍(lán)橋杯 第1次模擬賽真題詳解及小結(jié)(校內(nèi)模擬)【Java版】
  • 2020年?第11屆 藍(lán)橋杯 第2次模擬賽真題詳解及小結(jié)【Java版】
  • 2020年?第11屆 藍(lán)橋杯 C/C++ B組 省賽真題詳解及小結(jié)【第1場(chǎng)省賽 2020.7.5】【Java版】
  • 2020年?第11屆 藍(lán)橋杯 Java B組 省賽真題詳解及小結(jié)【第1場(chǎng)省賽 2020.7.5】
  • 2020年?第11屆 藍(lán)橋杯 Java C組 省賽真題詳解及小結(jié)【第1場(chǎng)省賽 2020.7.5】

    • 第11屆 藍(lán)橋杯-第1、2次模擬(軟件類(lèi))真題-(2020年3月、4月)-官方講解視頻

    目? ?錄

    一、12.5MB

    二、最多邊數(shù)

    三、單詞重排

    解法一:全排列 + Set去重

    解法二:dfs

    四、括號(hào)序列

    解法一:手工計(jì)算

    解法二:遞歸

    五、反倍數(shù)

    六、凱撒加密

    解法一:字符串.toCharArray()

    解法二:add()函數(shù)

    七、螺旋

    八、擺動(dòng)序列

    解法1:dfs

    優(yōu)化1:修改遞歸式

    優(yōu)化2:改為遞推

    九、通電

    十、植樹(shù)

    解法一

    優(yōu)化

    小結(jié)


    ? ?模擬賽(第二輪)真題解析-官方講解視頻

    一、12.5MB

    【問(wèn)題描述】

    在計(jì)算機(jī)存儲(chǔ)中,12.5MB是多少字節(jié)?

    【答案提交】

    這是一道結(jié)果填空的題,你只需要算出結(jié)果后提交即可。本題的結(jié)果為一個(gè)整數(shù),在提交答案時(shí)只填寫(xiě)這個(gè)整數(shù),填寫(xiě)多余的內(nèi)容將無(wú)法得分。

    【答案】:13107200

    【解析】:1K=1024字節(jié)? ?∴ 12.5*1024*1024

    ? ??

    • 1Byte(字節(jié)) =?8bit(位)? ?1K =?1024Byte(字節(jié))? ?
    • 字節(jié)也叫baiByte,是計(jì)算機(jī)數(shù)據(jù)的基本存儲(chǔ)單位,在電腦du里一個(gè)中zhi文字占兩個(gè)字節(jié)。

    二、最多邊數(shù)

    【問(wèn)題描述】

    一個(gè)包含有2019個(gè)結(jié)點(diǎn)的有向圖,最多包含多少條邊?(不允許有重邊)

    【答案提交】

    這是一道結(jié)果填空的題,你只需要算出結(jié)果后提交即可。本題的結(jié)果為一個(gè)整數(shù),在提交答案時(shí)只填寫(xiě)這個(gè)整數(shù),填寫(xiě)多余的內(nèi)容將無(wú)法得分。

    【答案】:4074342

    【解析】:任意兩點(diǎn)組成邊,邊有向,一來(lái)一回算兩條邊。? ? ? ?所以是n中選2的組合數(shù)乘以2級(jí)n*(n-1)

    ? ? ? ? ? ?最大邊數(shù) =??* 2 ,∴?最大邊數(shù) = ( 2019 * 2018 / 2 ) * 2 =?4074342

    ? ?? ?計(jì)算器?計(jì)算 即可!

    三、單詞重排

    【問(wèn)題描述】

    將LANQIAO中的字母重新排列,可以得到不同的單詞,如LANQIAO、AAILNOQ等,注意這7個(gè)字母都要被用上,單詞不一定有具體的英文意義。

    請(qǐng)問(wèn),總共能排列出多少個(gè)不同的單詞。

    【答案提交】

    這是一道結(jié)果填空的題,你只需要算出結(jié)果后提交即可。本題的結(jié)果為一個(gè)整數(shù),在提交答案時(shí)只填寫(xiě)這個(gè)整數(shù),填寫(xiě)多余的內(nèi)容將無(wú)法得分。

    【答案】:2520

    【解析】:全排列?+ 去重 + 計(jì)數(shù)

    解法一:全排列 + Set去重

    package simulationMatch_11_2020_2;import java.util.HashSet; import java.util.Set;public class _03_單詞重排 {static Set<String> set = new HashSet<String>(); // 不包含重復(fù)元素public static void main(String[] args) {char[] str = { 'L', 'A', 'N', 'Q', 'I', 'A', 'O' };f(str, 0);for(String x:set) {System.out.println(x);}System.out.println(set.size());}public static void f(char[] charArray, int k) {if (k == charArray.length) {String s = new String(charArray);set.add(s);}for (int i = k; i < charArray.length; i++) {char temp = charArray[i];charArray[i] = charArray[k];charArray[k] = temp;f(charArray, k + 1);temp = charArray[i];charArray[i] = charArray[k];charArray[k] = temp;}}}

    解法二:dfs

    package simulationMatch_11_2020_2;import java.util.HashSet; import java.util.Set;/*** @Author zhengwei* @Date 2020/5/17 5:32 PM* @Version 1.0*/ public class _03_單詞重排2 {private static char[] a = "LANQIAO".toCharArray();private static Set<String> ans = new HashSet<>();private static char[] tmp = new char[7];private static boolean[] vis = new boolean[7];public static void main(String[] args) {dfs(0);System.out.println(ans.size());}private static void dfs(int k) {if (k == 7) {ans.add(new String(tmp));return;}for (int i = 0; i < 7; i++) {if (!vis[i]) { // 沒(méi)有被選入tmp[k] = a[i];vis[i] = true;dfs(k + 1); // 確定下一位vis[i] = false; // 回溯}}} }

    四、括號(hào)序列

    【問(wèn)題描述】

    由1對(duì)括號(hào),可以組成一種合法括號(hào)序列:()。

    由2對(duì)括號(hào),可以組成兩種合法括號(hào)序列:()()、(())。

    由4對(duì)括號(hào)組成的合法括號(hào)序列一共有多少種?

    【答案提交】

    這是一道結(jié)果填空的題,你只需要算出結(jié)果后提交即可。本題的結(jié)果為一個(gè)整數(shù),在提交答案時(shí)只填寫(xiě)這個(gè)整數(shù),填寫(xiě)多余的內(nèi)容將無(wú)法得分。

    【答案】:14

    解法一:手工計(jì)算

    統(tǒng)計(jì)“4對(duì)括號(hào)組成的合法括號(hào)序列”,可以分為4種情況:

  • 括號(hào)不嵌套:()()()()
  • 1個(gè)括號(hào)嵌套1個(gè)括號(hào):(())()()、()(())()、()()(())、(())(())
  • 1個(gè)括號(hào)嵌套2個(gè)括號(hào):((()))()、()((()))、(()())()、()(()())
  • 1個(gè)括號(hào)嵌套3個(gè)括號(hào):(((())))、(()()())、(()(()))、((())())、((()()))
  • ∴ 1+4+4+5

    解法二:遞歸

    典型的遞歸結(jié)構(gòu),每個(gè)位置有兩種選擇,要么左括號(hào),要么右括號(hào)。

    選左括號(hào)的條件:可選數(shù)>0 且 變化后存在的左括號(hào)數(shù)量始終大于等于已存在的右括號(hào)數(shù)量。

    選右括號(hào)類(lèi)似。

    package simulationMatch_11_2020_2;/*** @Author zhengwei* @Date 2020/5/17 5:42 PM* @Version 1.0*/public class _04_括號(hào)序列 {public static void main(String[] args) {System.out.println(solve(4, 4, 4));}/**** @param n 對(duì)的數(shù)量* @param l 剩余左括號(hào)數(shù)量* @param r 剩余右括號(hào)的數(shù)量* @return*/private static int solve(int n, int l, int r) {if (l == 0 && r == 0)return 1;int ans = 0;// # 要么選左括號(hào),要么選右括號(hào)// # 選左括號(hào)的條件:l>0 且 變化后存在的左括號(hào)數(shù)量始終大于等于已存在的右括號(hào)數(shù)量if (l > 0 && n - (l - 1) >= n - r)ans += solve(n, l - 1, r);if (r > 0 && n - l >= n - (r - 1))ans += solve(n, l, r - 1);return ans;}}

    五、反倍數(shù)

    【問(wèn)題描述】

    給定三個(gè)整數(shù) a, b, c,如果一個(gè)整數(shù)既不是 a 的整數(shù)倍 也不是 b 的整數(shù)倍 還不是 c 的整數(shù)倍,則這個(gè)數(shù)稱(chēng)為反倍數(shù)。

    請(qǐng)問(wèn)在 1 至 n 中有多少個(gè)反倍數(shù)。

    【輸入格式】

    輸入的第一行包含一個(gè)整數(shù) n。

    第二行包含三個(gè)整數(shù) a, b, c,相鄰兩個(gè)數(shù)之間用一個(gè)空格分隔。

    【輸出格式】

    輸出一行包含一個(gè)整數(shù),表示答案。

    【樣例輸入】

    30

    2 3 6

    【樣例輸出】

    10

    【樣例說(shuō)明】

    以下這些數(shù)滿(mǎn)足要求:1, 5, 7, 11, 13, 17, 19, 23, 25, 29。

    【評(píng)測(cè)用例規(guī)模與約定】

    對(duì)于 40% 的評(píng)測(cè)用例,1 <= n <= 10000。

    對(duì)于 80% 的評(píng)測(cè)用例,1 <= n <= 100000。

    對(duì)于所有評(píng)測(cè)用例,1 <= n <= 1000000,1 <= a <= n,1 <= b <= n,1 <= c <= n。

    【解析】:迭代 + check

    package simulationMatch_11_2020_2;import java.util.Scanner;public class _05_反倍數(shù) {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt();int a = sc.nextInt();int b = sc.nextInt();int c = sc.nextInt();int answer = 0;for (int i = 1; i <= n; i++) { // i < n + 1if (i % a != 0 && i % b != 0 && i % c != 0) {answer++;}}System.out.println(answer);}}

    六、凱撒加密

    【問(wèn)題描述】

    給定一個(gè)單詞,請(qǐng)使用凱撒密碼將這個(gè)單詞加密。

    凱撒密碼是一種替換加密的技術(shù),單詞中的所有字母都在字母表上向后偏移3位后被替換成密文。即a變?yōu)閐,b變?yōu)閑,...,w變?yōu)閦,x變?yōu)閍,y變?yōu)閎,z變?yōu)閏。

    例如,lanqiao會(huì)變成odqtldr。

    【輸入格式】

    輸入一行,包含一個(gè)單詞,單詞中只包含小寫(xiě)英文字母。

    【輸出格式】

    輸出一行,表示加密后的密文。

    【樣例輸入】

    lanqiao

    【樣例輸出】

    odqtldr

    【評(píng)測(cè)用例規(guī)模與約定】

    對(duì)于所有評(píng)測(cè)用例,單詞中的字母?jìng)€(gè)數(shù)不超過(guò)100。

    【解析】:?遍歷 + 轉(zhuǎn)換,再拼成字符串

    解法一:字符串.toCharArray()

    package simulationMatch_11_2020_2;import java.util.Scanner;public class _06_凱撒加密 {public static void main(String[] args) {Scanner sc = new Scanner(System.in);String str = sc.next();char[] temp = str.toCharArray();for (int i = 0; i < str.length(); i++) {if (temp[i] == 'x') {temp[i] = 'a';} else if (temp[i] == 'y') {temp[i] = 'b';} else if (temp[i] == 'z') {temp[i] = 'c';} else {temp[i] += 3;}}System.out.println(new String(temp)); // 字符數(shù)組轉(zhuǎn)字符串 // for (char x : temp) { // System.out.print(x + ""); // }}}

    解法二:add()函數(shù)

    package simulationMatch_11_2020_2;import java.util.Scanner;/*** @Author zhengwei* @Date 2020/5/17 5:51 PM* @Version 1.0*/ public class _06_凱撒加密2 {private static char add(char letter) {if (letter < 'x')return (char) (letter + 3);else if (letter == 'x')return 'a';else if (letter == 'y')return 'b';elsereturn 'c';}public static void main(String[] args) {Scanner sc = new Scanner(System.in);String s = sc.next();char[] ans = new char[s.length()];for (int i = 0; i < s.length(); i++) {ans[i] = add(s.charAt(i));}System.out.println(new String(ans));} }

    七、螺旋

    【問(wèn)題描述】

    對(duì)于一個(gè) n 行 m 列的表格,我們可以使用螺旋的方式給表格依次填上正整數(shù),我們稱(chēng)填好的表格為一個(gè)螺旋矩陣。

    例如,一個(gè) 4 行 5 列的螺旋矩陣如下:

    1 2 3 4 5

    14 15 16 17 6

    13 20 19 18 7

    12 11 10 9 8

    【輸入格式】

    輸入的第一行包含兩個(gè)整數(shù) n, m,分別表示螺旋矩陣的行數(shù)和列數(shù)。

    第二行包含兩個(gè)整數(shù) r, c,表示要求的行號(hào)和列號(hào)。

    【輸出格式】

    輸出一個(gè)整數(shù),表示螺旋矩陣中第 r 行第 c 列的元素的值。

    【樣例輸入】

    4 5

    2 2

    【樣例輸出】

    15

    【評(píng)測(cè)用例規(guī)模與約定】

    對(duì)于 30% 的評(píng)測(cè)用例,2 <= n, m <= 20。

    對(duì)于 70% 的評(píng)測(cè)用例,2 <= n, m <= 100。

    對(duì)于所有評(píng)測(cè)用例,2 <= n, m <= 1000,1 <= r <= n,1 <= c <= m。

    【解析】:按題意生成網(wǎng)格,再取單元格中的數(shù)據(jù)?

    package simulationMatch_11_2020_2;import java.util.Scanner;public class _07_螺旋 {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt();int m = sc.nextInt();int r = sc.nextInt();int c = sc.nextInt();int[][] grid = new int[n][m];int num = 1;int up = 0, down = n, left = 0, right = m;while (true) {for (int col = left; col < right; col++) {grid[up][col] = num;num++;}up++;if (up == down)break;for (int row = up; row < down; row++) {grid[row][right - 1] = num;num++;}right--;if (left == right)break;for (int col = right - 1; col >= left; col--) {grid[down - 1][col] = num;num++;}down -= 1;if (up == down)break;for (int row = down - 1; row >= up; row--) {grid[row][left] = num;num++;}left++;if (left == right)break;}System.out.println(grid[r - 1][c - 1]);}} /** int[][] array = new int[n][m]; int x = 1; // 遞增數(shù)字 int index = 0; // 循環(huán)標(biāo)志 int count = n / 2 + n % 2; // 循環(huán)結(jié)束判斷標(biāo)識(shí) while (count > 0) {for (int i = index; i < m; i++) { // 第1行array[0][i] = x++;}for (int i = 1; i < n; i++) { // 第m列(最后一列)array[i][m - 1] = x++;}for (int i = m; i > 0; i--) { // 第n行(最后一行)array[n - 1][i - 1] = (x++ - 1);}for (int i = n - 1; i > 0; i--) { // 第1列array[i][0] = (x++ - 2);}index++;for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {System.out.print(array[i][j] + " ");}System.out.println();}System.out.println("------");count--; } */

    八、擺動(dòng)序列

    【問(wèn)題描述】

    如果一個(gè)序列的奇數(shù)項(xiàng)都比前一項(xiàng)大,偶數(shù)項(xiàng)都比前一項(xiàng)小,則稱(chēng)為一個(gè)擺動(dòng)序列。即 a[2i]<a[2i-1], a[2i+1]<a[2i]。

    小明想知道,長(zhǎng)度為 m,每個(gè)數(shù)都是 1 到 n 之間的正整數(shù)的擺動(dòng)序列一共有多少個(gè)。

    【輸入格式】

    輸入一行包含兩個(gè)整數(shù) m,n。

    【輸出格式】

    輸出一個(gè)整數(shù),表示答案。答案可能很大,請(qǐng)輸出答案除以10000的余數(shù)。

    【樣例輸入】

    3 4

    【樣例輸出】

    14

    【樣例說(shuō)明】

    以下是符合要求的擺動(dòng)序列:

    2 1 2

    2 1 3

    2 1 4

    3 1 2

    3 1 3

    3 1 4

    3 2 3

    3 2 4

    4 1 2

    4 1 3

    4 1 4

    4 2 3

    4 2 4

    4 3 4

    【評(píng)測(cè)用例規(guī)模與約定】

    對(duì)于 20% 的評(píng)測(cè)用例,1 <= n, m <= 5;

    對(duì)于 50% 的評(píng)測(cè)用例,1 <= n, m <= 10;

    對(duì)于 80% 的評(píng)測(cè)用例,1 <= n, m <= 100;

    對(duì)于所有評(píng)測(cè)用例,1 <= n, m <= 1000。

    解法1:dfs

    多數(shù)人都能想到:第1位,可選為[2,n]
    選定第1位(last1),開(kāi)始選第2位,可選為[1,last1-1],對(duì)所有l(wèi)ast1結(jié)果求和
    選定第2位(last2),開(kāi)始選第3位,可選為[last2+1,n],對(duì)所有l(wèi)ast2結(jié)果求和
    ……
    選定奇數(shù)位(last),開(kāi)始選下一個(gè)偶數(shù)位,可選為[1,last-1],對(duì)所有l(wèi)ast結(jié)果求和
    選定偶數(shù)位(last),開(kāi)始選下一個(gè)奇數(shù)位,可選為[last+1,n],對(duì)所有l(wèi)ast結(jié)果求和
    ……

    遞歸式為:
    dfs(last, k) = Σdfs(i, k + 1) | k為奇數(shù),i from 1 to last-1
    dfs(last, k) = Σdfs(i, k + 1) | k為偶數(shù),i from last+1 to n

    而遞歸起點(diǎn)(選定第一位,可選是2 to n)也是一個(gè)循環(huán):

    for i in range(2, n + 1):ans = (ans + dfs(i, 1)) % MOD

    這里面有大量重復(fù)子問(wèn)題,所以可以記憶型遞歸;但只能過(guò)80%的數(shù)據(jù),因?yàn)閺?fù)雜度是O(N3)

    package simulationMatch_11_2020_2;import java.util.Scanner;public class _08_擺動(dòng)序列 {private static final int MOD = 10000;private static int[][] mem = new int[1000][1000];private static int n, m;// 第k個(gè)數(shù)確定為last時(shí),序列總數(shù)是多少// param last:確定的最后一個(gè)數(shù)// param k:last是第k個(gè)private static int dfs(int last, int k) {if (k == m)return 1;if (mem[last][k] != 0)return mem[last][k];// k是奇數(shù),k+1是偶數(shù),偶數(shù)位比前一個(gè)小if ((k & 1) == 1)for (int i = 1; i < last; i++)mem[last][k] = (mem[last][k] + dfs(i, k + 1)) % MOD;elsefor (int i = last + 1; i < n + 1; i++)mem[last][k] = (mem[last][k] + dfs(i, k + 1)) % MOD;return mem[last][k];}public static void main(String[] args) {Scanner sc = new Scanner(System.in);m = sc.nextInt();n = sc.nextInt();int ans = 0;// 第一位可以選2到nfor (int i = 2; i < n + 1; i++)ans = (ans + dfs(i, 1)) % MOD;System.out.println(ans);}} /** int answer = 0; int array[] = new int[m]; for (int i = 0; i < m; i++) {f(array); // 對(duì)數(shù)組元素進(jìn)行賦值if(m % 2 == 1) { // m是奇數(shù)for (int k = 2; k < m; k += 2) {if (array[k - 1] < array[k] && array[k] < array[k + 1]) {answer++;}}} else { // m是偶數(shù)for (int k = 0; k < m; k += 2) {if (array[k - 1] < array[k] && array[k] < array[k + 1]) {answer++;}}} } System.out.println(answer % 10000); */

    優(yōu)化1:修改遞歸式

    這種在遞歸中加總的遞歸形態(tài),往往可以通過(guò)優(yōu)化遞歸式來(lái)改進(jìn),將遞歸式變成有匯總 or 集合的意義,就可以減少一層循環(huán),從而把復(fù)雜度變?yōu)镺(N2)

    可以從遞歸起點(diǎn)的那個(gè)循環(huán)考慮,我們既然要加總第1位選2到n的這若干種情況的結(jié)果,為什么不用dfs(2,1)直接表示第一位選[2,n]這所有情況的和呢?這就是集合的概念了。

    更通用地:
    k為奇數(shù)時(shí),dfs(x,k)表示第k位選[x,n]這若干種情況的種數(shù)和;
    k為偶數(shù)時(shí),dfs(x,k)表示第k位選[1,x]這若干種情況的種數(shù)和;
    但是怎么拆呢?技巧是拆成一個(gè)元素+一個(gè)(少了該元素的)小集合,小集合動(dòng)一個(gè)變量(往往代表規(guī)模),那拆出來(lái)的元素往往可以轉(zhuǎn)換成另外一個(gè)集合。

    就本題來(lái)說(shuō),k為奇數(shù)時(shí),dfs(x,k)可以這樣拆:

    k為偶數(shù)時(shí),dfs(x,k)可以這樣拆:

    ?
    那么可得遞歸式:

    dfs(x, k) = dfs(x+1, k) + dfs(x-1,k+1) | k為奇數(shù)
    dfs(x, k) = dfs(x-1, k) + dfs(x+1,k+1) | k為偶數(shù)

    遞歸起點(diǎn)為:ans = dfs(2, 1)

    package simulationMatch_11_2020_2;import java.util.Scanner;public class _08_擺動(dòng)序列2_優(yōu)化1 {private static final int MOD = 10000;private static int[][] mem = new int[1000][1000];private static int n, m;// 第k個(gè)數(shù)確定為last時(shí),序列總數(shù)是多少// param last:確定的最后一個(gè)數(shù)// param k:last是第k個(gè)private static int dfs(int last, int k) {if (last < 1 || last > n)return 0;if (k == m) {// 奇數(shù),return 大于等于last的個(gè)數(shù);偶數(shù),小于等于last的個(gè)數(shù)if ((k & 1) == 1) {mem[last][k] = n - last + 1;} else {mem[last][k] = last;}return mem[last][k];}if (mem[last][k] != 0)return mem[last][k];if ((k & 1) == 1)// 注意看這里的拆解:當(dāng)前函數(shù)的含義是第k位選last~n的序列數(shù)總和,切成兩塊// 1:第k位選(last+1)到n的序列數(shù)總和,函數(shù)含義不變,第一個(gè)參數(shù)變?yōu)閘ast+1==》dfs(last + 1, k)// 2:第k位固定為last,那么第k+1位的選擇是從1到last-1(因k+1是偶數(shù))==》dfs(last - 1, k + 1)mem[last][k] = (dfs(last + 1, k) + dfs(last - 1, k + 1)) % MOD;else // 偶數(shù)mem[last][k] = (dfs(last - 1, k) + dfs(last + 1, k + 1)) % MOD;return mem[last][k];}public static void main(String[] args) {Scanner sc = new Scanner(System.in);m = sc.nextInt();n = sc.nextInt();System.out.println(dfs(2, 1));}}

    優(yōu)化2:改為遞推

    為什么還要優(yōu)化呢?因?yàn)檫@樣遞歸層次太深,會(huì)超出棧空間限制。

    遞推是遞歸的逆過(guò)程,因此我們觀察上述遞歸函數(shù)的出口,就知道怎么初始化dp數(shù)組,再按照與遞歸相逆的順序逐步生成遞推數(shù)組。

    遞歸出口:

    if (k == m) {// 奇數(shù),return 大于等于last的個(gè)數(shù);偶數(shù),小于等于last的個(gè)數(shù)if ((k & 1) == 1) {mem[last][k] = n - last + 1;} else {mem[last][k] = last;}return mem[last][k]; }

    轉(zhuǎn)變?yōu)閿?shù)組初始化:

    //初始化最后一列 for (int x = 1; x < n + 1; x++) {if ((m & 1) == 1)dp[x][m] = n - x + 1;elsedp[x][m] = x; }

    遞歸中,列數(shù)k是逐漸增大,直至最后一列,那么遞推中,應(yīng)該從最后一列反推到第一列。

    package simulationMatch_11_2020_2;import java.util.Scanner;public class _08_擺動(dòng)序列2_優(yōu)化2 {private static final int MOD = 10000;private static int[][] dp;private static int n, m;public static void main(String[] args) {Scanner sc = new Scanner(System.in);m = sc.nextInt();n = sc.nextInt();dp = new int[n + 1][m + 1];// 初始化最后一列for (int x = 1; x < n + 1; x++) {if ((m & 1) == 1)dp[x][m] = n - x + 1;elsedp[x][m] = x;}for (int k = m - 1; k > 0; k--) {// # 奇數(shù),x從大到小遍歷if ((k & 1) == 1)for (int x = n; x > 0; x--)dp[x][k] = ((x + 1 <= n ? dp[x + 1][k] : 0) + dp[x - 1][k + 1]) % MOD;// # 偶數(shù),x從小到大遍歷elsefor (int x = 1; x < n + 1; x++)dp[x][k] = (dp[x - 1][k] + (x + 1 <= n ? dp[x + 1][k + 1] : 0)) % MOD;}System.out.println(dp[2][1]);}}

    九、通電

    【問(wèn)題描述】

    2015年,全中國(guó)實(shí)現(xiàn)了戶(hù)戶(hù)通電。作為一名電力建設(shè)者,小明正在幫助一帶一路上的國(guó)家通電。

    這一次,小明要幫助 n 個(gè)村莊通電,其中 1 號(hào)村莊正好可以建立一個(gè)發(fā)電站,所發(fā)的電足夠所有村莊使用。

    現(xiàn)在,這 n 個(gè)村莊之間都沒(méi)有電線相連,小明主要要做的是架設(shè)電線連接這些村莊,使得所有村莊都直接或間接的與發(fā)電站相通。

    小明測(cè)量了所有村莊的位置(坐標(biāo))和高度,如果要連接兩個(gè)村莊,小明需要花費(fèi)兩個(gè)村莊之間的坐標(biāo)距離加上高度差的平方,形式化描述為坐標(biāo)為 (x_1, y_1) 高度為 h_1 的村莊與坐標(biāo)為 (x_2, y_2) 高度為 h_2 的村莊之間連接的費(fèi)用為

    sqrt((x_1-x_2)*(x_1-x_2)+(y_1-y_2)*(y_1-y_2))+(h_1-h_2)*(h_1-h_2)。

    在上式中 sqrt 表示取括號(hào)內(nèi)的平方根。請(qǐng)注意括號(hào)的位置,高度的計(jì)算方式與橫縱坐標(biāo)的計(jì)算方式不同。

    由于經(jīng)費(fèi)有限,請(qǐng)幫助小明計(jì)算他至少要花費(fèi)多少費(fèi)用才能使這 n 個(gè)村莊都通電。

    【輸入格式】

    輸入的第一行包含一個(gè)整數(shù) n ,表示村莊的數(shù)量。

    接下來(lái) n 行,每個(gè)三個(gè)整數(shù) x, y, h,分別表示一個(gè)村莊的橫、縱坐標(biāo)和高度,其中第一個(gè)村莊可以建立發(fā)電站。

    【輸出格式】

    輸出一行,包含一個(gè)實(shí)數(shù),四舍五入保留 2 位小數(shù),表示答案。

    【樣例輸入】

    4

    1 1 3

    9 9 7

    8 8 6

    4 5 4

    【樣例輸出】

    17.41

    【評(píng)測(cè)用例規(guī)模與約定】

    對(duì)于 30% 的評(píng)測(cè)用例,1 <= n <= 10;

    對(duì)于 60% 的評(píng)測(cè)用例,1 <= n <= 100;

    對(duì)于所有評(píng)測(cè)用例,1 <= n <= 1000,0 <= x, y, h <= 10000。

    【解析】:最小生成樹(shù)

    可以說(shuō)是最小生成樹(shù)的裸題了——連通==樹(shù),代價(jià)最小==最小生成
    用Kruskal算法一氣呵成。
    不過(guò)要進(jìn)行一些處理:
    每個(gè)村莊看做是一個(gè)頂點(diǎn),編號(hào)存儲(chǔ)
    兩兩組成邊,用費(fèi)用做邊的權(quán)重

    做好數(shù)據(jù)處理,然后就是排序,從小到大把邊添加到最小生成樹(shù)的邊集(也不用真正添加,符合的邊把代價(jià)累加就行,不符合的邊忽略)

    符合與不符合,當(dāng)然要用并查集了。

    并查集 一定要掌握。

    package simulationMatch_11_2020_2;import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Scanner;public class _09_通電 {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt();// 接下來(lái) n 行,每個(gè)三個(gè)整數(shù) x, y, hint[][] data = new int[n + 1][3];for (int i = 1; i <= n; i++) {data[i][0] = sc.nextInt();data[i][1] = sc.nextInt();data[i][2] = sc.nextInt();}// # 將原始數(shù)據(jù)處理成邊集,每?jī)蓚€(gè)點(diǎn)一條邊,計(jì)算代價(jià)List<Edge> edges = new ArrayList<>(n * n);for (int i = 1; i <= n - 1; i++) {for (int j = i + 1; j <= n; j++) {edges.add(new Edge(i, j, cost(data[i], data[j])));}}// 對(duì)邊集排序Collections.sort(edges);// 初始化并查集工具UF uf = new UF(n);int edge_cnt = 0;double ans = 0;for (Edge e : edges) {if (uf.find(e.x) != uf.find(e.y)) {uf.union(e.x, e.y);edge_cnt++;ans += e.cost;if (edge_cnt == n - 1)break;}}System.out.printf("%.2f", ans);}/*** 封裝并查集操作*/private static class UF {int n;int[] parent;public UF(int n) {this.n = n;parent = new int[n + 1];for (int i = 1; i <= n; i++) {parent[i] = i;}}int find(int x) {if (parent[x] == x)return x;HashSet<Integer> path = new HashSet<>();while (parent[x] != x) {path.add(x);x = parent[x];}for (Integer xx : path) {parent[xx] = x;}return x;}void union(int a, int b) {parent[find(b)] = find(a);}}/*** 計(jì)算a,b兩個(gè)村莊的建設(shè)代價(jià)* * @param a* @param b* @return*/private static double cost(int[] a, int[] b) {return Math.sqrt((a[0] - b[0]) * (a[0] - b[0]) + (a[1] - b[1]) * (a[1] - b[1])) + (a[2] - b[2]) * (a[2] - b[2]);}/*** 注意實(shí)現(xiàn)Comparable接口*/private static class Edge implements Comparable<Edge> {int x;int y;double cost;public Edge(int x, int y, double cost) {this.x = x;this.y = y;this.cost = cost;}@Overridepublic int compareTo(Edge o) {return this.cost < o.cost ? -1 : (this.cost == o.cost ? 0 : 1);}}}

    十、植樹(shù)

    【問(wèn)題描述】

    小明和朋友們一起去郊外植樹(shù),他們帶了一些在自己實(shí)驗(yàn)室精心研究出的小樹(shù)苗。

    小明和朋友們一共有 n 個(gè)人,他們經(jīng)過(guò)精心挑選,在一塊空地上每個(gè)人挑選了一個(gè)適合植樹(shù)的位置,總共 n 個(gè)。他們準(zhǔn)備把自己帶的樹(shù)苗都植下去。

    然而,他們遇到了一個(gè)困難:有的樹(shù)苗比較大,而有的位置挨太近,導(dǎo)致兩棵樹(shù)植下去后會(huì)撞在一起。

    他們將樹(shù)看成一個(gè)圓,圓心在他們找的位置上。如果兩棵樹(shù)對(duì)應(yīng)的圓相交,這兩棵樹(shù)就不適合同時(shí)植下(相切不受影響),稱(chēng)為兩棵樹(shù)沖突。

    小明和朋友們決定先合計(jì)合計(jì),只將其中的一部分樹(shù)植下去,保證沒(méi)有互相沖突的樹(shù)。他們同時(shí)希望這些樹(shù)所能覆蓋的面積和(圓面積和)最大。

    【輸入格式】

    輸入的第一行包含一個(gè)整數(shù) n ,表示人數(shù),即準(zhǔn)備植樹(shù)的位置數(shù)。

    接下來(lái) n 行,每行三個(gè)整數(shù) x, y, r,表示一棵樹(shù)在空地上的橫、縱坐標(biāo)和半徑。

    【輸出格式】

    輸出一行包含一個(gè)整數(shù),表示在不沖突下可以植樹(shù)的面積和。由于每棵樹(shù)的面積都是圓周率的整數(shù)倍,請(qǐng)輸出答案除以圓周率后的值(應(yīng)當(dāng)是一個(gè)整數(shù))。

    【樣例輸入】

    6

    1 1 2

    1 4 2

    1 7 2

    4 1 2

    4 4 2

    4 7 2

    【樣例輸出】

    12

    【評(píng)測(cè)用例規(guī)模與約定】

    對(duì)于 30% 的評(píng)測(cè)用例,1 <= n <= 10;

    對(duì)于 60% 的評(píng)測(cè)用例,1 <= n <= 20;

    對(duì)于所有評(píng)測(cè)用例,1 <= n <= 30,0 <= x, y <= 1000,1 <= r <= 1000。

    解法一

    【解析】:

    每個(gè)圓可以選也可以不選,但不知道哪種決策結(jié)果最大,只能先考慮暴力搜索每種情況,總可選數(shù)為2的n次方的深度優(yōu)先搜索。

    某一個(gè)圓在準(zhǔn)備選入的時(shí)候,可以判斷是否與之前已入選的圓沖突,如果沖突了,這條分支就可以不繼續(xù)了,這可以視為剪枝;但是判斷是否沖突的check函數(shù)要遍歷已入選的圓,復(fù)雜度依然高;

    【代碼1】在n等于30的時(shí)候會(huì)吃不消。

    package simulationMatch_11_2020_2;import java.util.Scanner;public class _10_植樹(shù) {static Scanner sc = new Scanner(System.in);static int n;static int ans = 0;static Tree[] trees;static int[][] adjaTable;public static void main(String[] args) {n = sc.nextInt();initTrees();initAdjaTable();dfs(0, 0);System.out.println(ans);}/*** 初始化鄰接矩陣*/private static void initAdjaTable() {adjaTable = new int[n][n];for (int i = 0; i < n - 1; i++) {for (int j = i + 1; j < n; j++) {if (trees[i].intersected(trees[j])) {adjaTable[i][j] = 1;adjaTable[j][i] = 1;}}}}/*** 初始化每棵樹(shù)并加入數(shù)組*/private static void initTrees() {trees = new Tree[n];for (int i = 0; i < n; i++) {trees[i] = new Tree(sc.nextInt(), sc.nextInt(), sc.nextInt());}}private static void dfs(int sum, int index) {// 邊界if (index == n) {ans = Math.max(ans, sum);return;}// 2.選這棵樹(shù)(是有條件的)if (ok(index)) {trees[index].selected = true;int r = trees[index].r;dfs(sum + r * r, index + 1);trees[index].selected = false; // 回溯}// 1.不選當(dāng)前這棵樹(shù)trees[index].selected = false;dfs(sum, index + 1);}private static boolean ok(int index) {for (int i = 0; i < index; i++) {// i被選入,且i與當(dāng)前準(zhǔn)備入選的index相交,則index代表的樹(shù)不能入選if (trees[i].selected && adjaTable[i][index] == 1)return false;}return true;}private static class Tree {int x, y, r;boolean selected; // 是否入選public Tree(int x, int y, int r) {this.x = x;this.y = y;this.r = r;}/** 與另一顆樹(shù)是否相交 */public boolean intersected(Tree other) {int dis = (this.x - other.x) * (this.x - other.x) + (this.y - other.y) * (this.y - other.y);return dis < (this.r + other.r) * (this.r + other.r);}}}

    優(yōu)化

    優(yōu)化的關(guān)鍵點(diǎn)在于用類(lèi)似貪心的辦法(但不是貪心):將圓按半徑從大到小排序,這樣優(yōu)先考慮半徑大的圓的選與不選問(wèn)題;另外把“選”這個(gè)分支放在“不選”這個(gè)分支前面執(zhí)行,這樣我們相信會(huì)盡早地遇到最優(yōu)解。

    基于這個(gè)假設(shè),在遞歸之前我們可以以O(shè)(N)的復(fù)雜度存儲(chǔ)所有圓的“半徑的平方”的后綴和,計(jì)為數(shù)組s;在遞歸函數(shù)dfs中,參數(shù)sum代表index之前的選擇策略所得到的sum,s[index]代表包括index索引及之后續(xù)所有圓的半徑的平方和,如果sum+s[index]小于等于已經(jīng)求得的ans,那就不必進(jìn)行任何后續(xù)的選擇試探了,可立即退出遞歸。

    實(shí)測(cè),【代碼2】在n=30時(shí)能秒出結(jié)果。

    package simulationMatch_11_2020_2;import java.time.Duration; import java.time.Instant; import java.util.Arrays; import java.util.Scanner;public class _10_植樹(shù)2 {static Scanner sc = new Scanner(System.in);static int n;static int ans = 0;static Tree[] trees;static int[][] adjaTable;/** 半徑的平方后綴和 */static int[] suffix;public static void main(String[] args) {// Instant now = Instant.now();n = sc.nextInt();initTrees();initSuffix();initAdjaTable();dfs(0, 0);System.out.println(ans);// System.err.println("Duration:" + Duration.between(now,// Instant.now()).toMillis());}private static void initSuffix() {suffix = new int[n];suffix[n - 1] = trees[n - 1].pow_r;for (int i = n - 2; i >= 0; i--) {// 后綴和加當(dāng)前項(xiàng)的平方suffix[i] = suffix[i + 1] + trees[i].pow_r;}}/*** 初始化鄰接矩陣*/private static void initAdjaTable() {adjaTable = new int[n][n];for (int i = 0; i < n - 1; i++) {for (int j = i + 1; j < n; j++) {if (trees[i].intersected(trees[j])) {adjaTable[i][j] = 1;adjaTable[j][i] = 1;}}}}/*** 初始化每棵樹(shù)并加入數(shù)組*/private static void initTrees() {trees = new Tree[n];for (int i = 0; i < n; i++) {trees[i] = new Tree(sc.nextInt(), sc.nextInt(), sc.nextInt());}// !!!!排序Arrays.sort(trees);}private static void dfs(int sum, int index) {// 邊界if (index == n) {ans = Math.max(ans, sum);return;}// !!!如果index之前的sum加上自index開(kāi)始的半徑的平方和小于ans,則沒(méi)必要繼續(xù)if (sum + suffix[index] <= ans)return;// 2.選這棵樹(shù)(是有條件的)if (ok(index)) {trees[index].selected = true;dfs(sum + trees[index].pow_r, index + 1);trees[index].selected = false; // 回溯}// 1.不選當(dāng)前這棵樹(shù)trees[index].selected = false;dfs(sum, index + 1);}private static boolean ok(int index) {for (int i = 0; i < index; i++) {// i被選入,且i與當(dāng)前準(zhǔn)備入選的index相交,則index代表的樹(shù)不能入選if (trees[i].selected && adjaTable[i][index] == 1)return false;}return true;}private static class Tree implements Comparable<Tree> {int x, y, r, pow_r;boolean selected; // 是否入選public Tree(int x, int y, int r) {this.x = x;this.y = y;this.r = r;pow_r = r * r;}/** 與另一顆樹(shù)是否相交 */public boolean intersected(Tree other) {int dis = (this.x - other.x) * (this.x - other.x) + (this.y - other.y) * (this.y - other.y);return dis < (this.r + other.r) * (this.r + other.r);}@Overridepublic int compareTo(Tree o) {return this.r - o.r;}} }

    小結(jié)

    Python組 第9題 練功

    擴(kuò)展多少步達(dá)到目標(biāo),一般用bfs求解。

    bfs、dfs:走過(guò)的路 不再走。

    BufferedWriter:對(duì)輸出進(jìn)行優(yōu)化。緩沖式輸出,內(nèi)存積累到一定量,才向控制臺(tái)進(jìn)行輸出。

    總結(jié)

    以上是生活随笔為你收集整理的2020年 第11届 蓝桥杯 第2次模拟赛真题详解及小结【Java版】的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。