2019 第十屆藍橋杯Java省賽B組個人題解
前言
以下的第十屆藍橋杯Java B組省賽的題目題解只是我個人的題解,提供一些解題思路,僅作參考,如有錯誤,望大家指出,不勝感激,我會及時更改。
本來想把比賽題目上傳到CSDN上免費下載,上傳之後發現默認是5積分(根據下載熱度和評星積分會自己調整),後來瞭解到現在的CSDN向知識付費靠攏,激勵用戶上傳資源,取消了用戶自行定價的功能和下架資源的功能(需要找客服下架,客服根本不理啊)。
PS:CSDN可能是看到這個文章了嗎?題目可以免費下載了,0積分了,棒!!!
2019 第十屆藍橋杯Java省賽B組題目——CSDN(需要5或者更多積分(系統自己調的),希望大家儘量下載下面鏈接的,誰的積分來的都不容易)
2019 第十屆藍橋杯Java省賽B組題目下載——提取碼: yukk
試題A:組隊——答案:490
import java.util.Scanner;
/**
*
* @ClassName: Team組隊
* @Description: 題目不難理解,讓有的人迷糊的可能就是一個隊員只能選中一次。此題考試手動篩選一下就行,想寫程序驗證的也可以。
* @author: colou
* @date: 2019年3月30日 上午8:58:21
*/
public class Team組隊 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
try {
int[][] team = new int[20][5];
for (int i = 0; i < 20; i++) {
for (int j = 0; j < 5; j++) {
team[i][j] = input.nextInt();
}
}
int maxSum = 0;
for (int i = 0; i < 20; i++)
for (int j = 0; j < 20; j++)
for (int k = 0; k < 20; k++)
for (int h = 0; h < 20; h++)
for (int g = 0; g < 20; g++)
if ((i != j && i != k && i != h && i != g) && (j != k && j != h && j != g)
&& (k != h && k != g) && h != g) {
int max = team[i][0] + team[j][1] + team[k][2] + team[h][3] + team[g][4];
if (max > maxSum)
maxSum = max;
}
System.out.println(maxSum);
// 測試用例
/*
* 97 90 0 0 0 92 85 96 0 0 0 0 0 0 93 0 0 0 80 86 89 83 97 0 0 82 86 0 0 0 0 0
* 0 87 90 0 97 96 0 0 0 0 89 0 0 95 99 0 0 0 0 0 96 97 0 0 0 0 93 98 94 91 0 0
* 0 0 83 87 0 0 0 0 98 97 98 0 0 0 93 86 98 83 99 98 81 93 87 92 96 98 0 0 0 89
* 92 0 99 96 95 81
*/
} catch (Exception e) {
input.close();
}
}
}
試題B:不同子串——答案:100
import java.util.HashSet;
import java.util.Set;
/**
*
* @ClassName: DifferentSubstring不同子串
* @Description: 審題發現要求是不同的非空子串,則想到Set集合去重,String.substring()方法求子串(一切 爲快速解題爲前提),然後我們發現它的子串規律爲一開始子串長度爲1,然後在爲2,……,最後爲原字符串,這就好 比切豆腐,一開始要求切成每刀間隔爲1豆腐塊,每次移動距離爲1,後來要求切成每刀間隔爲2豆腐塊,每次移動距離 爲1,……,直至爲整個大豆腐的大小。
* @author: colou
*/
public class DifferentSubstring不同子串 {
public static void main(String[] args) {
String target = "0100110001010001";
Set<String> sub = new HashSet<String>();
for (int step = 0; step <= target.length() - 1; step++) {
for (int beginIndex = 0, endIndex = 1 + step; endIndex <= target.length(); beginIndex++, endIndex++) {
sub.add(target.substring(beginIndex, endIndex));
}
}
System.out.println(sub.size());
}
}
試題C:數列求值——答案:4659
/**
*
* @ClassName: SequenceEvaluation數列求值
* @Description: 此題類似於斐波那契數列,但是所求20190324項的最後四位數字,要是單純按照斐波那契數列的
* 思想求下去,別說long類型,BigInteger類型都存不了這麼大的數,然後我們發現,所求
* 20190324項的最後四位數字(也就是變相的告訴我們運算過程只和每個數的後四位有關係),那 麼我們只需要保留每次運算結果的後四位就OK了,這樣絕對不會溢出。
* @author: colou
*/
public class SequenceEvaluation數列求值 {
public static void main(String[] args) {
int a = 1, b = 1, c = 1;
// 要是求第四項,則i < 4, 同理推得求20190324,則i < 20190324。
for (int i = 3; i < 20190324; i++) {
int temp = (a + b + c) % 10000;
a = b;
b = c;
c = temp;
}
System.out.println(c);
}
}
試題D:數的分解——答案:40785
/**
*
* @ClassName: DecompositionOfNumbers數的分解
* @Description: 首先我們分析組成2019的三個數有哪幾類?1.ABC類排列方式爲六種(ABC,ACB,BAC,BCA,
* CAB,CBA),2.AAB類排列方式有三種(AAB,ABA,BAA),3.AAA類排列方式一種。而題目要
* 求把 2019 分解成 3 個各不相同的正整數之和也就是說只保留ABC類的組合方式,j = i + 1,減少一半排列方式。
* @author: colou
*/
public class DecompositionOfNumbers數的分解 {
public static void main(String[] args) {
int n = 2019;
int num = 0;
for (int i = 1; i < n; i++) {
if ((i + "").indexOf("2") != -1 || (i + "").indexOf("4") != -1)
continue;
for (int j = i + 1; j < n; j++) {
if ((j + "").indexOf("2") != -1 || (j + "").indexOf("4") != -1)
continue;
int k = n - i - j;
if (i == k || j == k || i == j)
continue;
if (k > 0 && (k + "").indexOf("2") == -1 && (k + "").indexOf("4") == -1)
num++;
}
}
System.out.println(num / 3);
}
}
試題E:迷宮
答案:DDDDRRURRRRRRDRRRRDDDLDDRDDDDDDDDDDDDRDDRRRURRUURRDDDDRDRRRRRRDRRURRDDDRRRRUURUUUUUUULULLUUUURRRRUULLLUUUULLUUULUURRURRURURRRDDRRRRRDDRRDDLLLDDRRDDRDDLDDDLLDDLLLDLDDDLDDRRRRRRRRRDDDDDDRR
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
import java.util.Stack;
/**
* @ClassName: LabyrinthProblem迷宮問題
* @Description: 廣度優先搜索:https://blog.csdn.net/raphealguo/article/details/7523411
* https://blog.csdn.net/u011815404/article/details/79582206
* @author: colou
*/
public class Labyrinth迷宮 {
/*
* 深度優先可以這樣想,一個人迷路,遇到很多分叉路口,他只有一個人,並且想走出去,所以只能一個個嘗試,
* 一條道路走到黑,發現到頭了,然後再拐回去走剛纔這條路的其他分叉路口,最後發現這條路的所有分叉路口走完了
* ,選擇另外一條路繼續以上操作,直到所有的路都走過了。
* 廣度優先並不是這樣,一個人迷路,但是他有技能(分身術)它遇到分叉路口,不是選一個走,而是分身多個人都試試,
* 比如有A、B、C三個分叉路口,它A路走一步,緊接着B路也走一步,然後C路也趕緊走一步,步伐整齊統一,直到所有的路走過了。
*/ public static void main(String[] args) {
Scanner input = new Scanner(System.in);
try {
String s = "01010101001011001001010110010110100100001000101010"
+ "00001000100000101010010000100000001001100110100101"
+ "01111011010010001000001101001011100011000000010000"
+ "01000000001010100011010000101000001010101011001011"
+ "00011111000000101000010010100010100000101100000000"
+ "11001000110101000010101100011010011010101011110111"
+ "00011011010101001001001010000001000101001110000000"
+ "10100000101000100110101010111110011000010000111010"
+ "00111000001010100001100010000001000101001100001001"
+ "11000110100001110010001001010101010101010001101000"
+ "00010000100100000101001010101110100010101010000101"
+ "11100100101001001000010000010101010100100100010100"
+ "00000010000000101011001111010001100000101010100011"
+ "10101010011100001000011000010110011110110100001000"
+ "10101010100001101010100101000010100000111011101001"
+ "10000000101100010000101100101101001011100000000100"
+ "10101001000000010100100001000100000100011110101001"
+ "00101001010101101001010100011010101101110000110101"
+ "11001010000100001100000010100101000001000111000010"
+ "00001000110000110101101000000100101001001000011101"
+ "10100101000101000000001110110010110101101010100001"
+ "00101000010000110101010000100010001001000100010101"
+ "10100001000110010001000010101001010101011111010010"
+ "00000100101000000110010100101001000001000000000010"
+ "11010000001001110111001001000011101001011011101000"
+ "00000110100010001000100000001000011101000000110011"
+ "10101000101000100010001111100010101001010000001000"
+ "10000010100101001010110000000100101010001011101000"
+ "00111100001000010000000110111000000001000000001011"
+ "10000001100111010111010001000110111010101101111000";
int[][] labyrinth = new int[30][50];
for (int i = 0; i < 30; i++) {
for (int j = 0; j < 50; j++) {
labyrinth[i][j] = s.charAt(50 * i + j) - '0';
}
}
System.out.println(BFS(labyrinth, 30, 50));
} catch (Exception e) {
input.close();
}
}
public static String BFS(int[][] labyrinth, int row, int column) {
int[][] stepArr = { { -1, 0 }, { 0, 1 }, { 0, -1 }, { 1, 0 } };
String[] direction = { "U", "R", "L","D"};
int[][] visit = new int[row][column];// 標記是否已經訪問過
StringBuilder sb = new StringBuilder();
Node node = new Node(0, 0, -1, -1, 0, null);
Queue<Node> queue = new LinkedList<Node>();
Stack<Node> stack = new Stack<Node>();
queue.offer(node);
while (!queue.isEmpty()) {
Node head = queue.poll();
stack.push(head); // 用於回溯路徑
visit[head.x][head.y] = 1;
for (int i = 0; i < 4; i++) {
int x = head.x + stepArr[i][0];
int y = head.y + stepArr[i][1];
String d = direction[i];
// exit
if (x == row - 1 && y == column - 1 && labyrinth[x][y] == 0 && visit[x][y] == 0) {
// 打印路徑
Node top = stack.pop();
sb.append(d);
sb.append(top.direction);
int preX = top.preX;
int preY = top.preY;
while (!stack.isEmpty()) {
top = stack.pop();
if (preX == top.x && preY == top.y) {
if (top.direction != null)
sb.append(top.direction);
preX = top.preX;
preY = top.preY;
}
}
return sb.reverse().toString();
}
// bfs
if (x >= 0 && x < row && y >= 0 && y < column && labyrinth[x][y] == 0 && visit[x][y] == 0) {
Node newNode = new Node(x, y, head.x, head.y, head.step + 1, d);
queue.offer(newNode);
}
}
}
return null;
}
}
class Node {
int x, y;
int step;
int preX, preY;
String direction;
Node(int x, int y, int preX, int preY, int step, String direction) {
this.x = x;
this.y = y;
this.preX = preX;
this.preY = preY;
this.step = step;
this.direction = direction;
}
}
試題F:特別數的和
import java.util.Scanner;
/**
*
* @ClassName: SpecialSum特別數的和
* @Description: int轉String,使用String.indexOf();判斷包含不包含"2", "0", "1", "9",可以使用while循環加%,/運算判斷。
* @author: colou
*/
public class SpecialSum特別數的和 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
try {
int n = input.nextInt();
int sum = 0;
for (int i = 1; i <= n; i++) {
String target = Integer.toString(i);
if (target.indexOf("2") != -1 || target.indexOf("0") != -1 || target.indexOf("1") != -1
|| target.indexOf("9") != -1) {
sum += i;
}
}
System.out.println(sum);
} catch (Exception e) {
input.close();
}
}
}
試題G:外賣店優先級
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
/**
* @ClassName: TakeawayShopPriority外賣店優先級
* @Description: 創建一個記錄店鋪優先級的數組來存儲優先級,另外創建一個用來判斷每個時間點是否有訂單的數組(1代表有 ,0無)
* 這裏偷懶使用集合充當緩存,可以使用數組之類的。
* @author: colou
*/
public class TakeawayShopPriority外賣店優先級 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
try {
Set<Integer> set = new HashSet<Integer>();
int N = input.nextInt();
int M = input.nextInt();
int T = input.nextInt();
int[][] orders = new int[M][2];
for (int i = 0; i < M; i++) {
for (int j = 0; j < 2; j++) {
orders[i][j] = input.nextInt();
}
}
int[] priority = new int[N];
int[] sign = new int[N];
for (int i = 1; i <= T; i++) {
for (int j = 0; j < M; j++) {
if (orders[j][0] == i) {
priority[orders[j][1] - 1] += 2;
if (priority[orders[j][1] - 1] > 5 && !set.contains(orders[j][1] - 1)) {
set.add(orders[j][1] - 1);
}
sign[orders[j][1] - 1] = 1;
}
}
for (int j = 0; j < N; j++) {
if (sign[j] == 0 && priority[j] > 0)
priority[j]--;
if (priority[j] <= 3) {
set.remove(j);
}
}
sign = new int[N];
}
System.out.println(set.size());
} catch (Exception e) {
input.close();
}
}
}
試題H:人物相關性分析
import java.util.Scanner;
/**
*
* @ClassName: CharacterCorrelationAnalysis人物相關性分析
* @Description: "."和"|"都是轉義字符,必須得加"\\";
* @author: colou
*/
public class CharacterCorrelationAnalysis人物相關性分析 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
try {
int K = input.nextInt();
input.nextLine();
String text = input.nextLine();
//字符串分割,按照空格和.分割字符,若是(.空格)分割後爲空字符串。
String[] words = text.split("\\s+|\\.");
int[] wordsLength = new int[words.length];
//將分割的字符串的長度值存儲,避免三重循環中調用String.length();
for (int i = 0; i < words.length; i++) {
wordsLength[i] = words[i].length();
}
int num = 0;
//Alice ——> Bob的距離
for (int i = 0; i < words.length; i++) {
if (words[i].equals("Alice")) {
for (int j = i + 1; j < words.length; j++) {
int sum = 1;
if (words[j].equals("Bob")) {
for (int k = i + 1; k < j; k++) {
//每個單詞的長度加空格佔據的長度
sum += wordsLength[k] + 1;
}
if (sum <= K) {
num++;
}
}
}
}
}
//Bob ——> Alice的距離
for (int i = 0; i < words.length; i++) {
if (words[i].equals("Bob")) {
for (int j = i + 1; j < words.length; j++) {
int sum = 1;
if (words[j].equals("Alice")) {
for (int k = i + 1; k < j; k++) {
sum += wordsLength[k] + 1;
}
if (sum <= K) {
num++;
}
}
}
}
}
System.out.println(num);
} catch (Exception e) {
input.close();
}
}
}
試題I:後綴表達式
import java.util.Arrays;
import java.util.Scanner;
/**
* @ClassName: PostfixExpression後綴表達式
* @Description: 這道題我的思想是分情況討論:
* 1.如果只有+號,沒有-號,則遍歷數組累加即可;
* 2.如果只有-號,沒有+號,首先從小到大排序,然後分兩種情況考慮:
* (1).最小值是負數(也就是含有負數),例如[-2, -1, 3, 4, 5],四個減號,運算過程爲5 - (-1) - (-2 - 3 - 4) = 5 + 1 - (-9)
* = 5 + 1 + 9 = 15,也就是說只要含有負數,負數轉正數,全部相加即可
* (2).最小值是正數(全部是正數),例如[1, 2, 3],兩個減號,運算過程爲3 - (1 - 2) = 3 + 2 - 1,也就是說運算規則爲除了
* 最小值以外的正數相加減去最小值
* 3.如果有+號,有-號,則討論減號的個數與負數的個數,分兩種情況討論(實際分爲三種):
*( 1).減號個數大於等於負數個數(則將負數變正數,每一個負數變正數的過程中, 減號的數量需要減一,然後排序,遍歷數組從大到小累加,
* 直至剩下的數字個數和減號數量相同,然後再減去這些剩下的數字);
* (2).減號個數小於負數個數,這個時候我們就應該使用+號,消除負數(比如[2, -5 , -6, + , -],運算過程爲2 - ((-5) + (-6)) =
* 2 + 11 = 13),我們可以再分情況討論:
* (2.1).全是負數,如[-1, -2, -3, -4, -5],其中一個加號三個減號,運算過程爲(-1 - ((-4) + (-5)) - (-3) - (-2) = -1 + 9
* + 3 + 2),則運算規律爲首先排序選擇其中的最大值,加上其他數字的絕對值就行(可以自行繼續證明)。(2.2).有正數,有負數,
* [-1, 19, 17, -4, -5],其中兩個加號兩個減號,則運算過程爲(19 + 17 - ((-4) + (-5)) - (-1) = 19 + 17 + 9 + 1),則運算
* 規律爲首先排序選擇其中的最大值,加上其他數字的絕對值就行(可以自行繼續證明)。所有情況討論完畢。
* @author: colou
*/
public class PostfixExpression後綴表達式 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
try {
int add = input.nextInt();
int reduce = input.nextInt();
int totalLength = add + reduce + 1;
int[] number = new int[totalLength];
for (int i = 0; i < totalLength; i++) {
number[i] = input.nextInt();
}
int sum = 0;
if (reduce == 0) {
for (int i = 0; i < totalLength; i++) {
sum += number[i];
}
}
if (add == 0) {
Arrays.sort(number);
if (number[0] < 0) {
for (int i = 0; i <= reduce; i++) {
if (number[i] > 0)
sum += number[i];
else
sum -= number[i];
}
} else {
for (int i = 1; i <= reduce; i++) {
sum += number[i];
}
sum -= number[0];
}
}
if (add != 0 && reduce != 0) {
int reduceNum = 0;
for (int i = 0; i < totalLength; i++) {
if (number[i] < 0) {
reduceNum++;
}
}
if (reduce >= reduceNum) {
Arrays.sort(number);
int temp = reduce;
for (int i = 0; i < reduceNum; i++) {
number[i] = -number[i];
temp--;
}
Arrays.sort(number);
for (int i = totalLength - 1; i >= temp; i--) {
sum += number[i];
}
for (int i = temp - 1; i >= 0; i--) {
sum -= number[i];
}
} else {
Arrays.sort(number);
sum += number[totalLength - 1];
for (int i = 0; i < totalLength - 1; i++) {
if (number[i] > 0)
sum += number[i];
else
sum -= number[i];
}
}
}
System.out.println(sum);
} catch (Exception e) {
input.close();
}
}
}
至此完畢,最後一題想偷個懶,等看了之後再更新,如果有錯誤,請閱讀者評論指出,不勝感激。