我参加的第二届(2020年),国二
12月20日的决赛,因为抓期末复习,所以现在才出这篇题解
决赛有6个编程题
文末可下载题目和源码
一
题目描述
某高校食堂开办了一个自助餐厅,使用智能餐盘和自动结算,计算学生餐费。
智能餐盘能够识别所打莱品类型,重量,单价(计价单位为:元/100克)
食堂计划以每道菜、汤独立定价;主食200克以内免费,200克以上部分收费(如果打了多道主食,依据输入次序累计免费200克以下部分)
为鼓励学生健康饮食,学校鼓励学生联网分享运动信息,参照计步数进行阶梯折扣,0-5999步不打折,6000-9999为9折,10000步以上均为8折。
试根据餐盘提供的信息和学生的计步数,计算该同学某次用餐的最终餐费
输入说明
第1行为该生本次用餐所打的所有饭菜种类数量N0 < N ≤ 10)
第2行起每一行顺序为盘中每道饭菜的信息,包括:类型(M:荤菜/:素菜/R:主食/S:汤)、重量(克,整数单价(元/100克)
第N+2行为该同学的计步数。
输出说明
最终餐费(保留两位小数)
输入样例
6
M 50 3.00
V 100 1.50
M 50 5.00
V 150 2.00
R 150 0.10
S 150 0.00
8754
输出样例
7.65
题解
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 本次的所有饭菜种类数量
int n = scanner.nextInt();
// 吸收换行符
scanner.nextLine();
// 总费用
double result = 0;
// Rweight:主食的重量, flag:是否有200g
int Rwight = 0, flag = 0;
for (int i = 0; i < n; i++) {
String shiwu = scanner.next();
int weight = scanner.nextInt();
double price = scanner.nextDouble();
// 当前的食物是主食
if("R".equals(shiwu)){
Rwight += weight;
// 主食小于200克 免费
if (Rwight <= 200) {
result += 0;
}
// 主食大于200g,但是还没有被免费
else if(flag == 0){
result += ((double)(Rwight - 200)) / 100 * price;
// 以后的主食不再免费
flag = 1;
}
// 后续主食不再免费
else {
result += ((double)weight) / 100 * price;
}
}
// 除主食之外的食物
else {
result += ((double)weight) / 100 * price;
}
}
int num = scanner.nextInt();
// 按照步数来打折
if(6000 <= num && num < 10000) {
result *= 0.9;
} else if(num >= 10000) {
result *= 0.8;
}
System.out.printf("%.2f", result);
}
}
二
题目描述
给定序列的前两项a1,a2,请产生符合下列要求的前10项整数序列:
若当前序列的最后2项的乘积为5位数以内的数,则把积作为其后继项;
否则后继项全为0
输入说明
两个整数a1,a2
输出说明
输出符合条件的前10项数字。
数字之间用空格隔开,所有数据输出后换行。
输入样例
48
输出样例
3225681920000000
题解
考虑数据可能很大,用long型存储
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
long[] arr = new long[12];
arr[0] = scanner.nextLong();
arr[1] = scanner.nextLong();
for (int i = 2; i < 12; i++) {
long temp = arr[i - 1] * arr[i - 2];
// 考虑负数
arr[i] = -99999 <= temp && temp <= 99999 ? temp : 0;
}
for (int i = 2; i < 12; i++) {
System.out.print(arr[i]);
if(i < 11) {
System.out.print(" ");
} else {
// 题目要求 所有数据输出后换行
System.out.println();
}
}
}
}
三
题目描述
给定一个含有N个整数的序列(2<N<10000),输入一个整数K(K<N),从K的位置把该序列分为2个部分,分别为1到K部分,K+1到N部分。
然后在1到K部分执行从小到大排序;
在K+1到N部分执行从大到小排序(即前—部分从小到大,后部分从大到小);
然后再在这两部分分别执行前半部分数据(注:前半部分数据的长度上取整,可参考样例)从小到大排序,后半部分数据从大到小排序;
最后输出该整数序列
输入说明
第一行是正整数N(2<N<1000),正整数K(1<=K<N)
第二行依次输入这N个数。
输出说明
经过操作后的这N个数的序列。数字之间用空格隔开,所有数据输出后换行。
输入样例
10512345678910
输出样例
12354891076
题解
利用java 的排序工具:Arrays.sort(int[] arr, int fromIndex, int toIndex);
这个函数的排序时间复杂度为:O(nlogn)
为避免数据过大,采用long存储
import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int k = scanner.nextInt();
Long[] arr = new Long[n];
for (int i = 0; i < n; i++) {
arr[i] = scanner.nextLong();
}
// 1(第一个数)到K部分执行从小到大排序
Arrays.sort(arr, 0, k);
// K+1到N部分执行从大到小排序
Arrays.sort(arr, k, n, new Comparator<Long>() {
@Override
public int compare(Long o1, Long o2) {
return (int) (o2 - o1);
}
});
// 第一段的中间
int index1 = (k + 1) / 2;
Arrays.sort(arr, index1, k, new Comparator<Long>() {
@Override
public int compare(Long o1, Long o2) {
return (int) (o2 - o1);
}
});
// 第二段的中间
int index2 = k + (n - k + 1) / 2;
Arrays.sort(arr, k, index2);
for (int i = 0; i < n; i++) {
System.out.print(arr[i]);
if(i < n - 1) {
System.out.print(" ");
} else {
// 题目要求 所有数据输出后换行
System.out.println();
}
}
}
}
四
题目描述
某字符串描述了一个单循环链表,但并非严格按照节点的顺序关系给出,两个节点的前后关系描述如下:
每个中括号中包含一个节点及其后继节点,节点名称由小写字母和数字组成,之间由”->”连接,表示前驱后继关系
如[node1->node2] [node3->node1] [node2->node3]表示链表节点的顺序为node1->node2->node3->node1
输入一个字符串,给定两个节点名称,输出前一节点到后一节点的距离长度
输入说明
第一行为单循环链表的描述字符串(长度 ≤ 200)
第二行是两个节点的名称,节点A节点B,以空格隔开。
输出说明
节点A到节点B的距离(计A到B的距离长度,而不是B到A)
输入样例
[node1->node2] [node3->node1] [node 2->node3] 注:两对中括号之间没有空格
nodel node3
输出样例
2
题解
利用HashMap存储键值对
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 读入描述单循环链表的字符串
String string = scanner.nextLine();
Map<String, String> map = new HashMap<>();
// 开始、结束结点
String startNode = scanner.next();
String endNode = scanner.next();
int n = string.length();
// 解析单链表,存储到map中
for (int i = 0; i < n; i++) {
if (string.charAt(i) == '[') {
String key = string.substring(i + 1, i + 6);
String value = string.substring(i + 8, i + 13);
map.put(key, value);
}
}
int result = 0;
// 从开始结点开始寻找
String curr = startNode;
while (true) {
// 获取下一个结点
String value = map.get(curr);
// 步数加一
++result;
// 找到了就输出步数,然后结束
if (value.equals(endNode)) {
System.out.println(result);
break;
}
// 下一个结点变为当前结点,继续往下找
curr = value;
}
}
}
五
公交车换乘城市推出了优惠换乘活动
乘客第一次在公交车上打卡后,可以免费同站台换乘2次
现给出城市中多条公交路线,每个公交站有一个编号,编号由一个字母和一位或两位数字组成。
给定某乘客的出发站,问2次换乘,最多可以经过多少个不同的公交站
输入说明
第一行是一个整数N(1<N<=20)和出发站编号,其中N表示公交路线数量。
接下来N行,每行表示—条公交路线的所有停靠站编号(单条线路的停靠站数量少于20),中间用空格隔开。
已知公交线路不会形成环线
输出说明
一个整数,表示不超过2次换乘,最多可以经过多少个不同的公交站。
输入样例
3 C3
A1 A2 A3
C1 C2 C3 C4
A2 B1 C2 D1
输出样例
5
题解
暂时还不会,,,,,,
六
题目描述
东方公司有很多员工,任意两个员工要么是朋友,要么不是朋友
公司需要参加一个铁三角活动,选出三名员工,要求这三名员工中任意两员工都是朋友关系,现在请你计算出一共有多少种选择方法。
输入说明
第一行一个正整数N,表示一共有N名员工,员工编号1~N(N不超过2000);
接下来输入若干行(不超过50万行),每行两个1到N之间的正整数y1和y2,表示编号y1员工和编号y2员工是朋友关系,以两个零
(00)表示关系输入结束;
没有输入的都是非朋友关系。
输出说明
可组成铁三角的选择方法总数。
输入样例
5
1 2
1 3
2 4
3 4
2 3
5 2
0 0
输出样例
3
题解
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Scanner;
public class Main {
static int n;
static boolean[] visited;
static int[] arr = new int[3];
static Map<Integer, HashSet<Integer>> map = new HashMap<>();
static int count = 0;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
n = scanner.nextInt();
visited = new boolean[n + 1];
int a = scanner.nextInt();
int b = scanner.nextInt();
for (int i = 1; i <= n; i++) {
map.put(i, new HashSet<>());
}
while (a != 0 && b != 0) {
map.get(a).add(b);
a = scanner.nextInt();
b = scanner.nextInt();
}
dfs(0);
// 答案之间含有重复
System.out.println(count / 6);
/*for (Map.Entry<Integer, LinkedList<Integer>> entry: map.entrySet()){
System.out.println(entry.getKey());
System.out.println(entry.getValue());
}*/
}
private static void dfs(int i) {
if (i == 3) {
++count;
} else {
for (int j = 1; j <= n; j++) {
arr[i] = j;
if (!visited[j] && judge(i)) {
visited[j] = true;
dfs(i + 1);
visited[j] = false;
}
}
}
}
private static boolean judge(int i) {
// 第一个选谁都可以
if (i == 0) {
return true;
}
// 选择的第二个必须和第一个是朋友关系
else if (i == 1) {
HashSet<Integer> hashSet = map.get(arr[0]);
if (hashSet.contains(arr[1])) {
return true;
}
hashSet = map.get(arr[1]);
return hashSet.contains(arr[0]);
}
// 选择的第三个必须和第一个,第二个是朋友关系
else {
boolean oneAndThree = false, twoAndThree = false;
HashSet<Integer> hashSet = map.get(arr[0]);
if (hashSet.contains(arr[2])) {
oneAndThree = true;
}
hashSet = map.get(arr[1]);
if (hashSet.contains(arr[2])) {
twoAndThree = true;
}
hashSet = map.get(arr[2]);
if (hashSet.contains(arr[0])) {
oneAndThree = true;
}
if (hashSet.contains(arr[1])) {
twoAndThree = true;
}
return oneAndThree && twoAndThree;
}
}
}
这个决赛就结束了,官方命题范围
题目和代码下载:全国高校计算机能力挑战全国总决赛java