CCF签到题,没有提到分数的题目都是100分,不然会额外提出,样例输入都单独文本复制粘贴了,这样你们测试的时候很方便粘贴用例,不用自己手敲,都是一些签到题。但有好的基础,会多的数据结构,好的数学思想,那么这些都是一些很简单的问题。因为java版本不多,所以仅供参考,以下代码的思路都很简单,很多都直接通过题目面向过程,有更好的想法,或者你我有些题没有满分的改进方式都可以交流。
CCF300分的线,1、2题需要拿满,最低也要190,第三题是理解题,很多时候考你的语文能力更多,第四题是规律性更强的题,涉及图论算法众多(最小生成树3题,通信网络,最优灌溉,数据中心,地铁修建)(最短路径4题,最优匹配,无线网络,交通规划,游戏)(欧拉图,强连通分支,最长路径也都考过),还有正则匹配的题(5题url映射,json查询,markdown,模板生成系统,字符中匹配),总而言之一句话,第4题规律性很强。你只需要1、2题拿满,第4题拿90,第五题和第三题通过理解之后,暴力得分,就能稳300分以上,不排除某年的题会难、杂,或者当年当月你不在巅峰,那就下一次再考,上面列举的题型出现的频率极高,针对1、2、4刷题性价比是最高的。
下面只提供了第一题和第二题,因为在线测试对java语言不太友好,导致我的3、4题分数参差不齐,所以没有提供代码,网上有众多优秀的博客,输入试题编号和名称即可找到,看看思路,自己再写一遍,算法之路,任重道远。(数学很重要,数学是编程的降维武器)
试题编号:201312-1
试题名称:出现次数最多的数
样例输入
6
10 1 10 20 30 20
样例输出
10
思路:解决方法有很多,要么空间够大开够,用下标去加加计数,或者用hashset一直塞,重复会返回default,然后default就对应加加,用indexof找,唯一值,还可以用一个数组,在插入时注意排序,因为需要输出最小值,插入时就排好序,重复的就加加次数,总之方法很多。
import java.util.Scanner; public class CCF201312_1 { public static void main(String[] args) { Scanner sc=new Scanner(System.in); int n=sc.nextInt(); int[] space=new int[n]; for(int i=0;i<n;i++) { space[i]=sc.nextInt(); } int[] flag=new int[10000]; for(int i=0;i<n;i++) { flag[space[i]]++; } int max=0; int index=0; int finded=0; for(int i=0;i<10000;i++) { if(flag[i]!=0) { finded=finded+flag[i]; } if(flag[i]>max) { max=flag[i]; index=i; } if(finded==n) { break; } } System.out.println(index); } }
试题编号:201312-2
试题名称:ISBN号码
样例输入
0-670-82162-0
样例输出
0-670-82162-4
思路:问题描述中已经有具体步骤了,对于格式统一,下标固定的问题,基本数据结构掌握就可以解决。
import java.util.Scanner; public class CCF201312_2 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); String sourse = sc.nextLine(); int ret = 1 * (sourse.charAt(0) - '0') + 2 * (sourse.charAt(2) - '0') + 3 * (sourse.charAt(3) - '0') + 4 * (sourse.charAt(4) - '0') + 5 * (sourse.charAt(6) - '0') + 6 * (sourse.charAt(7) - '0') + 7 * (sourse.charAt(8) - '0') + 8 * (sourse.charAt(9) - '0') + 9 * (sourse.charAt(10) - '0'); ret = ret % 11; if (sourse.charAt(12) == 'X') {// 如果默认为X if (ret == 10) {// 匹配对 System.out.print("Right"); return; } else {// 不匹配 for (int i = 0; i < sourse.length() - 1; i++) { System.out.print(sourse.charAt(i)); } System.out.print(ret); } } else {//默认不是X if ((sourse.charAt(12) - '0') == ret) { System.out.print("Right"); return; } if (ret == 10) { for (int i = 0; i < sourse.length() - 1; i++) { System.out.print(sourse.charAt(i)); } System.out.print("X"); return; } else { for (int i = 0; i < sourse.length() - 1; i++) { System.out.print(sourse.charAt(i)); } System.out.print(ret); } } } }
试题编号:201403-1
试题名称:相反数
样例输入
5
1 2 3 -1 -2
样例输出
2
思路:给了范围,不会超过一千,用二维数组,正负分开在二维数组上加加,然后判断有多少对即可,用finded去记录找到的数目,可以提前退出循环,提高速度。
import java.util.Scanner; public class CCF201403_1 { public static void main(String[] args) { Scanner sc=new Scanner(System.in); int N=sc.nextInt(); int[] sourse=new int[N]; int[][] flag=new int[1000][2]; for(int i=0;i<N;i++) { sourse[i]=sc.nextInt(); if(sourse[i]>0) { flag[sourse[i]][1]++; } else { flag[-1*sourse[i]][0]++; } } int finded=0; int count=0; for(int i=0;i<1000;i++) { if(flag[i][0]>0||flag[i][1]>0) { finded+=flag[i][0]+flag[i][1]; } if((flag[i][0]>flag[i][1])&&(flag[i][1]>0)) { count+=flag[i][1]; } if((flag[i][1]>flag[i][0])&&(flag[i][0]>0)) { count+=flag[i][0]; } if((flag[i][1]==flag[i][0])&&flag[i][1]>0) { count+=flag[i][0]; } if(finded==N) { break; } } System.out.println(count); } }
试题编号:201403-2
试题名称:窗口
样例输入
3 4
0 0 4 4
1 1 5 5
2 2 6 6
1 1
0 0
4 4
0 5
样例输出
2
1
1
IGNORED
样例说明
第一次点击的位置同时属于第 1 和第 2 个窗口,但是由于第 2 个窗口在上面,它被选择并且被置于顶层。
第二次点击的位置只属于第 1 个窗口,因此该次点击选择了此窗口并将其置于顶层。现在的三个窗口的层次关系与初始状态恰好相反了。
第三次点击的位置同时属于三个窗口的范围,但是由于现在第 1 个窗口处于顶层,它被选择。
最后点击的 (0, 5) 不属于任何窗口。
思路:这题有点意思,但是题目中告诉你窗口是自下向上给出,而窗口在上方的又具有更高的优先级,所以用数组存取每一层窗口的坐标,下标越高的窗口优先级就越高,从后往前遍历,看chick的点是否在当前层之内,如果在就输出,并且用newone函数去把当前窗口的级别调整到最高,也就是向数组的最后部推,这样优先级即为最高,实现比较器会比较方便交换,这里直接用temp值交换了。
import java.util.Scanner; public class CCF201403_2 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int N = sc.nextInt(); int M = sc.nextInt(); int[][] Sourse = new int[N][5]; for (int i = 0; i < N; i++) { Sourse[i][0] = sc.nextInt(); Sourse[i][1] = sc.nextInt(); Sourse[i][2] = sc.nextInt(); Sourse[i][3] = sc.nextInt(); Sourse[i][4]=i+1; } int[][] chick = new int[M][2]; for (int i = 0; i < M; i++) { chick[i][0] = sc.nextInt(); chick[i][1] = sc.nextInt(); } int key = 0; for (int i = 0; i < M; i++) { int j; for (j = N - 1; j >= 0; j--) { if ((Sourse[j][0] <= chick[i][0]) && (chick[i][0] <= Sourse[j][2]) && (Sourse[j][1] <= chick[i][1]) && (chick[i][1] <= Sourse[j][3])) { System.out.println(Sourse[j][4]); Sourse = newOne(Sourse, j); break; } } if (j == -1) { System.out.println("IGNORED"); } } } public static int[][] newOne(int[][] Sourse, int key) { int n = Sourse.length - 1; int tempX1 = Sourse[key][0]; int tempY1 = Sourse[key][1]; int tempX2 = Sourse[key][2]; int tempY2 = Sourse[key][3]; int tempIndex=Sourse[key][4]; for (int i = key; i < n; i++) { Sourse[i][0] = Sourse[i + 1][0]; Sourse[i][1] = Sourse[i + 1][1]; Sourse[i][2] = Sourse[i + 1][2]; Sourse[i][3] = Sourse[i + 1][3]; Sourse[i][4] = Sourse[i + 1][4]; } Sourse[n][0] = tempX1; Sourse[n][1] = tempY1; Sourse[n][2] = tempX2; Sourse[n][3] = tempY2; Sourse[n][4]=tempIndex; return Sourse; } }
试题编号:201409-1
试题名称:相邻数对
样例输入
6
10 2 6 3 7 8
样例输出
3
样例说明
值正好相差1的数对包括(2, 3), (6, 7), (7, 8)。
评测用例规模与约定
1<=n<=1000,给定的整数为不超过10000的非负整数。
思路:因为数值最大为10000,但要考虑重复的情况,第一题一般对时间空间没有什么要求,用下标去加加计数,然后通过循环去获取相邻差为1的整数对,用finded去对找到的点进行计数提前退出,然后去找连续的重复值加到ret上即可。
import java.util.Scanner; public class CCF201409_1 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int[] sourse = new int[n]; int[] space = new int[10000]; for (int i = 0; i < n; i++) { sourse[i] = sc.nextInt(); space[sourse[i]]++; } int ret = 0; int finded = 0; for (int i = 0; i < 9999; i++) { if (space[i] > 0) { finded += space[i]; if (space[i + 1] > 0) { ret += space[i + 1]; } } if (finded == n) { break; } } System.out.println(ret); } }
试题编号:201409-2
试题名称:画图
样例输入
2
1 1 4 4
2 3 6 5
样例输出
15
评测用例规模与约定
1<=n<=100,0<=横坐标、纵坐标<=100。
思路: 简单的遍历,涂色,网络上还有逆向思路的,去计算最大正方形,然后扣空,但不易操作,所以通过开辟空间使问题简单化
import java.util.Scanner; public class CCF201409_2 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int[][] space = new int[n][4]; int minX = 100; int maxX = 0; int minY = 100; int maxY = 0; for (int i = 0; i < n; i++) { space[i][0] = sc.nextInt(); if (space[i][0] < minX) { minX = space[i][0]; } space[i][1] = sc.nextInt(); if (space[i][1] < minY) { minY = space[i][1]; } space[i][2] = sc.nextInt(); if (space[i][2] > maxX) { maxX = space[i][2]; } space[i][3] = sc.nextInt(); if (space[i][3] > maxY) { maxY = space[i][3]; } } int[][] color = new int[maxX - minX][maxY - minY]; for (int i = 0; i < n; i++) { for (int j = space[i][0] - minX; j < space[i][2] - minX; j++) { for (int k = space[i][1] - minY; k < space[i][3] - minY; k++) { color[j][k]++; } } } int ret = 0; for (int i = 0; i < maxX - minX; i++) { for (int j = 0; j < maxY - minY; j++) { if (color[i][j] > 0) { ret++; } } } System.out.println(ret); } }
试题编号:201412-1
试题名称:门禁系统
样例输入
5
1 2 1 1 3
样例输出
1 1 2 3 1
评测用例规模与约定
1≤n≤1,000,读者的编号为不超过n的正整数。
思路:很水的题,直接边读边输出就行了。
import java.util.Scanner; public class CCF201412_1 { public static void main(String[] args) { Scanner sc=new Scanner(System.in); int n=sc.nextInt(); int[] array=new int[1000]; for(int i=0;i<n;i++) { System.out.println(++array[sc.nextInt()]); } } }
试题编号:201412-2
试题名称:Z字形扫描
样例输入
4
1 5 3 9
3 7 5 6
9 4 6 4
7 3 1 3
样例输出
1 5 3 9 7 3 9 5 4 7 3 6 6 4 1 3
评测用例规模与约定
1≤n≤500,矩阵元素为不超过1000的正整数。
思路:也是一道比较有意思的题,但是找到规律之后也很简单,首先分奇偶,然后把拐角的点和直线的点都写出来,就发现出现的情况是一定对称的,不论奇偶都是对称的,拐点是周期性循环变化,拐弯之后的直线周期性增加,当到对角线时操作最长为y,不理解的同学可以把过程的点都写出来,然后在这些点之间,把x++,或y++的变化过程标上去,就一目了然了。最后不要忘记特殊情况的处理。还理解不了的可以结合着图,并且通过debug模式去一步一步的推算,规律题。
import java.util.Scanner; public class CCF201412_2 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int[][] Z = new int[n][n]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { Z[i][j] = sc.nextInt(); } } if (n == 1) { System.out.print(Z[0][0]); return; } if (n == 2) { System.out.print(Z[0][0] + " " + Z[0][1] + " " + Z[1][0] + " " + Z[1][1]); return; } int x = 0; int y = 0; int flag = 1; int choose = 1; System.out.print(Z[x][y] + " "); choose = -1; while (flag != n) { if (choose == -1) { System.out.print(Z[x][++y] + " "); for (int i = 0; i < flag; i++) { System.out.print(Z[++x][--y] + " "); } choose = 1; } else { System.out.print(Z[++x][y] + " "); for (int i = 0; i < flag; i++) { System.out.print(Z[--x][++y] + " "); } choose = -1; } flag++; } flag--; flag--; choose = choose * -1; while (flag != 0) { if (choose == -1) { System.out.print(Z[x][++y] + " "); for (int i = 0; i < flag; i++) { System.out.print(Z[--x][++y] + " "); } choose = 1; } else { System.out.print(Z[++x][y] + " "); for (int i = 0; i < flag; i++) { System.out.print(Z[++x][--y] + " "); } choose = -1; } flag--; } System.out.print(Z[x][++y]); } }
试题编号:201503-1
试题名称:图像旋转
样例输入
2 3
1 5 3
3 2 4
样例输出
3 4
5 2
1 3
评测用例规模与约定
1 ≤ n, m ≤ 1,000,矩阵中的数都是不超过1000的非负整数。
思路:存进去,读出来就行,就是一个相对坐标转化。这代码跑的时候,一次过,一次超时的。。。神奇的在线测试。
import java.util.Scanner; public class CCF201503_1 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int m = sc.nextInt(); int n=sc.nextInt(); int[][] ret=new int[n][m]; for(int j=0;j<m;j++) { for(int i=n-1;i>=0;i--) { ret[i][j]=sc.nextInt(); } } for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { System.out.print(ret[i][j]+" "); } System.out.print(" "); } } }
试题编号:201503-2
试题名称:数字排序
样例输入
12
5 2 3 3 1 3 4 2 5 2 3 5
样例输出
3 4
2 3
5 3
1 1
4 1
评测用例规模与约定
1 ≤ n ≤ 1000,给出的数都是不超过1000的非负整数。
思路:简单题,别把自己绕进去就行,就一个排序,排序时注意出现次数一样多,先输出小的。用了冒泡排序。
package CCF; import java.util.Arrays; import java.util.HashSet; import java.util.Scanner; public class CCF201503_2 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int[] sourse = new int[n]; HashSet hs = new HashSet(); for (int i = 0; i < n; i++) { sourse[i] = sc.nextInt(); hs.add(sourse[i]); } Arrays.sort(sourse); int sizes = hs.size(); int[][] ret = new int[sizes][2]; int flag = 0; for (int i = 0; i < n; i++) { if (i == 0) { ret[flag][0] = sourse[i]; ret[flag][1]++; continue; } if (sourse[i] == ret[flag][0]) {// 如果和前一个相等 ret[flag][1]++; } else {// 和前一个不相等 flag++; ret[flag][0] = sourse[i]; ret[flag][1]++; } } int temp0 = 0; int temp1 = 0; for (int i = 0; i < sizes; i++) { for (int j = 0; j < sizes - 1 - i; j++) { if (ret[j + 1][1] > ret[j][1]) { temp0 = ret[j + 1][0]; temp1 = ret[j + 1][1]; ret[j + 1][0] = ret[j][0]; ret[j + 1][1] = ret[j][1]; ret[j][0] = temp0; ret[j][1] = temp1; continue; } if (ret[j + 1][1] == ret[j][1]) { if (ret[j + 1][0] < ret[j][0]) { temp0 = ret[j + 1][0]; temp1 = ret[j + 1][1]; ret[j + 1][0] = ret[j][0]; ret[j + 1][1] = ret[j][1]; ret[j][0] = temp0; ret[j][1] = temp1; } } } } for (int i = 0; i < sizes; i++) { System.out.println(ret[i][0] + " " + ret[i][1]); } } }
试题编号:201509-1
试题名称:数列分段
样例输入
8
8 8 8 0 12 12 8 0
样例输出
5
样例说明
8 8 8是第一段,0是第二段,12 12是第三段,倒数第二个整数8是第四段,最后一个0是第五段。
评测用例规模与约定
1 ≤ n ≤ 1000,0 ≤ ai ≤ 1000。
思路:就是边读边判断是否和前一个一样,如果一样不操作,不一样就加加。
import java.util.Scanner; public class CCF201509_1 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); if (n == 1) { System.out.println(1); } int[] A = new int[n]; int ret = 1; for (int i = 0; i < n; i++) { A[i] = sc.nextInt(); if (i != 0) {// 除去第一个 if (A[i] != A[i - 1]) { ret++; } } } System.out.println(ret); } }
试题编号:201509-2
试题名称:日期计算
样例输入
2015
80
样例输出
3
21
样例输入
2000
40
样例输出
2
9
思路:人基本常识必须要有,剩下的就是简答操作了。
import java.util.Scanner; public class CCF201509_2 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int year=sc.nextInt(); int d=sc.nextInt(); int[] mounth=new int[] {31,0,31,30,31,30,31,31,30,31,30,31}; if(((year%4==0)&&(year%100!=0))||(year%400==0)) { mounth[1]=29; } else { mounth[1]=28; } for(int i=0;i<12;i++) { if(d>mounth[i]) { d-=mounth[i]; } else { System.out.println(i+1); System.out.println(d); return; } } } }
试题编号:201512-1
试题名称:数位之和
样例输入
20151220
样例输出
13
样例说明
20151220的各位数字之和为2+0+1+5+1+2+2+0=13。
评测用例规模与约定
所有评测用例满足:0 ≤ n ≤ 1000000000。
思路:charAt的标准用法之一,注意char转int即可。
import java.util.Scanner; public class CCF201512_1 { public static void main(String[] args) { Scanner sc=new Scanner(System.in); String sourse=sc.nextLine(); int ret=0; for(int i=0;i<sourse.length();i++) { ret+=(sourse.charAt(i)-'0'); } System.out.println(ret); } }
试题编号:201512-2
试题名称:消除类游戏
样例输入
4 5
2 2 3 1 2
3 4 5 1 4
2 3 2 1 3
2 2 2 4 4
样例输出
2 2 3 0 2
3 4 5 0 4
2 3 2 0 3
0 0 0 4 4
样例说明
棋盘中第4列的1和第4行的2可以被消除,其他的方格中的棋子均保留。
样例输入
4 5
2 2 3 1 2
3 1 1 1 1
2 3 2 1 3
2 2 3 3 3
样例输出
2 2 3 0 2
3 0 0 0 0
2 3 2 0 3
2 2 0 0 0
样例说明
棋盘中所有的1以及最后一行的3可以被同时消除,其他的方格中的棋子均保留。
评测用例规模与约定
所有的评测用例满足:1 ≤ n, m ≤ 30。
思路:横向遍历一次,纵向遍历一次,用二维数组对可以消除的置1,并且因为3连可消,下标也直接已知,可以简化一点循环。
import java.util.Scanner; public class CCF201512_2 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int m = sc.nextInt(); int[][] ret = new int[n][m]; int[][] sourse = new int[n][m]; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { sourse[i][j] = sc.nextInt(); } } int[] flag = new int[2]; for (int i = 0; i < n; i++) { flag[0] = sourse[i][0]; flag[1] = 1; for (int j = 1; j < m; j++) { if (flag[0] == sourse[i][j]) { flag[1]++; } else { flag[0] = sourse[i][j]; flag[1] = 1; } if (flag[1] >= 3) { ret[i][j] = 1; ret[i][j - 1] = 1; ret[i][j - 2] = 1; } } } for (int j = 0; j < m; j++) { flag[0] = sourse[0][j]; flag[1] = 1; for (int i = 1; i < n; i++) { if (flag[0] == sourse[i][j]) { flag[1]++; } else { flag[0] = sourse[i][j]; flag[1] = 1; } if (flag[1] >= 3) { ret[i][j] = 1; ret[i - 1][j] = 1; ret[i - 2][j] = 1; } } } for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { if (ret[i][j] == 0) { System.out.print(sourse[i][j] + " "); } else { System.out.print(0 + " "); } } System.out.println(); } } }
试题编号:201604-1
试题名称:折点计数
样例输入
7
5 4 1 2 3 6 4
样例输出
2
评测用例规模与约定
所有评测用例满足:1 ≤ n ≤ 1000,每天的销售量是不超过10000的非负整数。
思路:用flag去记录前一组数据的斜率的正负,如果斜率正负变化,说明发生拐点。
import java.util.Scanner; public class CCF201604_1 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); if (n == 1) { int mm = sc.nextInt(); System.out.println(0); return; } if (n == 2) { int mm = sc.nextInt(); int mmm = sc.nextInt(); System.out.println(0); return; } int[] A = new int[n]; int flag = 0; int temp = 0; int ret = 0; for (int i = 0; i < n; i++) { A[i] = sc.nextInt(); if (i == 1) { flag = ZhengOrFu(A[0], A[1]); } if (i != 0) { temp = ZhengOrFu(A[i - 1], A[i]); if (temp != flag) { ret++; flag = temp; } } } System.out.println(ret); } public static int ZhengOrFu(int m, int n) { if ((n - m) >= 0) { return -1; } else { return 1; } } }
试题编号:201604-2
试题名称:俄罗斯方块
样例输入
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 1 0 0 0
1 1 1 0 0 0 1 1 1 1
0 0 0 0 1 0 0 0 0 0
0 0 0 0
0 1 1 1
0 0 0 1
0 0 0 0
3
样例输出
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 1 0 0 0
1 1 1 1 1 1 1 1 1 1
0 0 0 0 1 1 0 0 0 0
思路:这道题我只有90分,因为游戏界面优先,可显示的部分是固定的,所以计算极端情况,额外上下开辟一定空间(4,一个方块的大小),然后计算最多可下落的距离,直接刷新过去就可以了,没有满分可能是没有考虑到一些特殊情况,不过思路可以参考,网上也有很多优秀的简短代码,我的思想比较简单,并且需要改进。
import java.util.Scanner; public class CCF201604_2 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int[][] sourse = new int[23][10]; for (int i = 4; i < 19; i++) { for (int j = 0; j < 10; j++) { sourse[i][j] = sc.nextInt(); } } int[][] block = new int[4][4]; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { block[i][j] = sc.nextInt(); } } int startIndex = sc.nextInt() - 1; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if (block[i][j] != 0) { sourse[i][j + startIndex]++; } } } int[] minBlock = new int[4]; int[] minDepth = new int[4]; for (int j = 0; j < 4; j++) { for (int i = 3; i >= 0; i--) { if (block[i][j] == 0) { minBlock[j]++; } else { break; } } } for (int j = startIndex; j < startIndex + 4; j++) { for (int i = 4; i < 19; i++) { if (sourse[i][j] == 0) { minDepth[j - startIndex]++; } else { break; } } } int min = 19; int index = 0; for (int i = 0; i < 4; i++) { if ((minBlock[i] + minDepth[i]) < min) { min = minBlock[i] + minDepth[i]; index = i; } } for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if (block[i][j] == 1) { sourse[i + min][j + startIndex]++; } } } Print(sourse); } public static void Print(int[][] sourse) { for (int i = 4; i < 19; i++) { for (int j = 0; j < 10; j++) { System.out.print(sourse[i][j] + " "); } System.out.println(); } } }
试题编号:201609-1
试题名称:最大波动
样例输入
6
2 5 5 7 3 5
样例输出
4
样例说明
第四天和第五天之间的波动最大,波动值为|3-7|=4。
评测用例规模与约定
对于所有评测用例,2 ≤ n ≤ 1000。股票每一天的价格为1到10000之间的整数。
思路:边读数据,边计算差值,比较即可。
import java.util.Scanner; public class CCF201609_1 { public static void main(String[] args) { Scanner sc=new Scanner(System.in); int n=sc.nextInt(); int[] A=new int[n]; int max=0; for(int i=0;i<n;i++) { A[i]=sc.nextInt(); if(i!=0) { if(Math.abs((A[i]-A[i-1]))>max) { max=Math.abs(A[i]-A[i-1]); } } } System.out.println(max); } }
试题编号:201609-2
试题名称:火车购票
样例输入
4
2 5 4 2
样例输出
1 2
6 7 8 9 10
11 12 13 14
3 4
样例说明
1) 购2张票,得到座位1、2。
2) 购5张票,得到座位6至10。
3) 购4张票,得到座位11至14。
4) 购2张票,得到座位3、4。
评测用例规模与约定
对于所有评测用例,1 ≤ n ≤ 100,所有购票数量之和不超过100。
思路:这道题也只拿了90分,思想很简单,就是遍历每一个数组,去匹配剩余的空间,如果够就一口气插入,下标直接更新,数组当前层的大小(length)就是下一次需要插入的坐标,思路很简单,但是只有90分,特殊情况考虑不够,历年的一二题都比较简单,但是需要够细致,考虑完所有的特殊、极限情况。
import java.util.Scanner; public class CCF201609_2 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int[][] space = new int[20][5]; int[] sourse = new int[n]; for (int i = 0; i < n; i++) { int need = sc.nextInt(); sourse[i] = need; int flag = 0; for (int j = 0; j < 20; j++) {// 遍历每一排看空间 if (L(space, j) >= need) { for (int k = 0; k < need; k++) { space[j][5 - L(space, j)]++; System.out.print((j * 5 + 5 - L(space, j)) + " "); } flag = 1; break;// 跳出循环去接收下一个数据 } } if (flag == 0) { int temp = need; for (int j = 0; j < 20; j++) { if (temp == 0) { break; } if (L(space, j) > 0) { for (int k = 0; k < need; k++) { space[j][5 - L(space, j)]++; System.out.print((j * 5 + k + 1) + " "); temp--; } } } } System.out.println(); } } public static int L(int[][] space, int index) { int ret = 0; for (int i = 0; i < 5; i++) { if (space[index][i] == 0) { ret++; } } return ret; } }
试题编号:201612-1
试题名称:中间数
样例输入
6
2 6 5 6 3 5
样例输出
5
样例说明
比5小的数有2个,比5大的数也有2个。
样例输入
4
3 4 6 7
样例输出
-1
样例说明
在序列中的4个数都不满足中间数的定义。
样例输入
5
3 4 6 6 7
样例输出
-1
样例说明
在序列中的5个数都不满足中间数的定义。
评测用例规模与约定
对于所有评测用例,1 ≤ n ≤ 1000,1 ≤ ai ≤ 1000。
思路:还是喜欢前几年,用例给两个,并且给的用例面一半会比较广、不同。2种方式,都需要先排序,你要满足大于你的数等于小于你的数,即使是有重复数的情况,这个数也一定在排序后的中间位置上,用这个数去匹配去检验就可以,我的检验不够好,你可以从中间的下标,从中间为原点,左右匹配找到不同的数,然后通过下标计算直接得出大于小于的数的数量。第二种方式就是双向队列,弹头弹尾,注意检验就可以了。
import java.util.Arrays; import java.util.Scanner; public class CCF201612_1 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int[] sourse = new int[n]; for (int i = 0; i < n; i++) { sourse[i] = sc.nextInt(); } Arrays.sort(sourse); if (n % 2 == 0) { int a = sourse[n / 2 - 1]; int b = sourse[n / 2]; if (a == b) { int count = 0; for (int i = 0; i < n; i++) { if (sourse[i] < a) { count++; } if (sourse[i] > a) { count--; } } if (count == 0) { System.out.println(a); } else { System.out.println(-1); } } else { int countA = 0; int countB = 0; for (int i = 0; i < n; i++) { if (sourse[i] < a) { countA++; } if (sourse[i] > a) { countA--; } if (sourse[i] < b) { countB++; } if (sourse[i] > b) { countB--; } } if (countA == 0) { System.out.println(a); } if (countB == 0) { System.out.println(b); } else { System.out.println(-1); } } return; } if (n % 2 == 1) { int a = sourse[n / 2]; int count = 0; for (int i = 0; i < n; i++) { if (sourse[i] < a) { count++; } if (sourse[i] > a) { count--; } } if (count == 0) { System.out.println(a); } else { System.out.println(-1); } return; } } }
试题编号:201612-2
试题名称:工资计算
样例输入
9255
样例输出
10000
评测用例规模与约定
对于所有评测用例,1 ≤ T ≤ 100000。
思路:这个代码我写的很丑,这题也比较烦,数学的关系式推好了可以简化很多,不管是最后的折算计算出原值的结果,还是前面各种数据的转换,先写公式再做题,数学是编程的降维武器。
import java.util.Scanner; public class CCF201612_2 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int T = sc.nextInt(); if (T <= 3500) { System.out.println(T); return; } int[][] range = new int[7][2]; range[0][0] = 3500; range[0][1] = 3500; range[1][0] = (int) (range[0][0] + 1500 * (0.97)); range[1][1] = 5000; range[2][0] = (int) (range[1][0] + (4500 - 1500) * (0.9)); range[2][1] = 8000; range[3][0] = (int) (range[2][0] + (9000 - 4500) * (0.8)); range[3][1] = 12500; range[4][0] = (int) (range[3][0] + (35000 - 9000) * (0.75)); range[4][1] = 38500; range[5][0] = (int) (range[4][0] + (55000 - 35000) * (0.7)); range[5][1] = 58500; range[6][0] = (int) (range[5][0] + (80000 - 55000) * (0.65)); range[6][1] = 83500; int Index = 0; for (int i = 6; i >= 0; i--) { if (T > range[i][0]) { Index = i; break; } } double[] rate = new double[] { 0.97, 0.9, 0.8, 0.75, 0.7, 0.65, 0.55 }; for (int i = (range[Index][0] / 100 + 1) * 100; i < 100001; i += 100) { if (T == (range[Index][0] + (i - range[Index][1]) * rate[Index])) { System.out.println(i); return; } } } }
试题编号:201703-1
试题名称:分蛋糕
样例输入
6 9
2 6 5 6 3 5
样例输出
3
样例说明
第一个朋友分到了前3块蛋糕,第二个朋友分到了第4、5块蛋糕,第三个朋友分到了最后一块蛋糕。
评测用例规模与约定
对于所有评测用例,1 ≤ n ≤ 1000,1 ≤ k ≤ 10000,1 ≤ ai ≤ 1000。
思路:排序之后很好解决,顺着给就行,大于需求就下一个,不够满足了就输出结构就行。
import java.util.Arrays; import java.util.Scanner; public class CCF201703_1 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int k = sc.nextInt(); int[] A = new int[n]; for (int i = 0; i < n; i++) { A[i] = sc.nextInt(); } if (n == 1) { System.out.println(1); return; } int ret = 0; int temp = 0; for (int i = 0; i < n; i++) { if (temp < k) { temp += A[i]; } if (temp >= k) { temp = 0; ret++; } } if (temp != 0) { ret++; } System.out.println(ret); } }
试题编号:201703-2
试题名称:学生排队
样例输入
8
3
3 2
8 -3
3 -2
样例输出
1 2 4 3 5 8 6 7
评测用例规模与约定
对于所有评测用例,1 ≤ n ≤ 1000,1 ≤ m ≤ 1000,所有移动均合法。
思路:很简单的问题,其实用LinkedList也可以很好解决,毕竟有大量的移动操作,我的代码思路很简单,就顺着交换学生位置移动就行了。
import java.util.Scanner; public class CCF201703_2 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int m = sc.nextInt(); int[] sourse = new int[n]; for (int i = 0; i < n; i++) { sourse[i] = i + 1; } for (int i = 0; i < m; i++) { int num = sc.nextInt(); int step = sc.nextInt(); for (int j = 0; j < n; j++) { if (sourse[j] == num) { sourse = Move(sourse, j, step); break; } } } for (int i = 0; i < n; i++) { System.out.print(sourse[i] + " "); } } public static int[] Move(int[] sourse, int index, int step) { if (step == 0) { return sourse; } else if (step < 0) {// 向前动 int temp = 0; if ((step * -1) >= index) {// 超出移动范围 if (index == 0) { return sourse; } for (int i = index - 1; i >= 0; i--) { temp = sourse[i]; sourse[i] = sourse[i + 1]; sourse[i + 1] = temp; } return sourse; } else {// 范围内的移动 for (int i = index - 1; i > index - 1 + step; i--) { temp = sourse[i]; sourse[i] = sourse[i + 1]; sourse[i + 1] = temp; } return sourse; } } else { int temp = 0; if ((index + 1 + step) >= sourse.length) { if (index == sourse.length - 1) { return sourse; } for (int i = index; i < sourse.length - 1; i++) { temp = sourse[i]; sourse[i] = sourse[i + 1]; sourse[i + 1] = temp; } return sourse; } else { for (int i = index; i < index + step; i++) { temp = sourse[i]; sourse[i] = sourse[i + 1]; sourse[i + 1] = temp; } } return sourse; } } }
试题编号:201709-1
试题名称:打酱油
样例输入
40
样例输出
5
样例说明
把40元分成30元和10元,分别买3瓶和1瓶,其中3瓶送1瓶,共得到5瓶。
样例输入
80
样例输出
11
样例说明
把80元分成30元和50元,分别买3瓶和5瓶,其中3瓶送1瓶,5瓶送2瓶,共得到11瓶。
思路:先去满足优惠最高的,最好自己心算一下每一瓶的价格,然后依次满足较低的优惠,没办法再原价买,贪心思想。
import java.util.Scanner; public class CCF201709_1 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int N = sc.nextInt() / 10; if (N < 2) { System.out.println(N); return; } int ret = 0; int bestNum = N / 5; ret = (N / 5) * 5 + (N / 5) * 2; int lease = N % 5; if (lease == 0) { System.out.println(ret); return; } ret += (lease / 3) * 4; lease = lease % 3; if (lease == 0) { System.out.println(ret); return; } ret += lease; System.out.println(ret); } }
试题编号:201709-2
试题名称:公共钥匙盒
样例输入
5 2
4 3 3
2 2 7
样例输出
1 4 3 2 5
样例说明
第一位老师从时刻3开始使用4号教室的钥匙,使用3单位时间,所以在时刻6还钥匙。第二位老师从时刻2开始使用钥匙,使用7单位时间,所以在时刻9还钥匙。
每个关键时刻后的钥匙状态如下(X表示空):
时刻2后为1X345;
时刻3后为1X3X5;
时刻6后为143X5;
时刻9后为14325。
样例输入
5 7
1 1 14
3 3 12
1 15 12
2 7 20
3 18 12
4 21 19
5 30 9
样例输出
1 2 3 5 4
评测用例规模与约定
对于30%的评测用例,1 ≤ N, K ≤ 10, 1 ≤ w ≤ N, 1 ≤ s, c ≤ 30;
对于60%的评测用例,1 ≤ N, K ≤ 50,1 ≤ w ≤ N,1 ≤ s ≤ 300,1 ≤ c ≤ 50;
对于所有评测用例,1 ≤ N, K ≤ 1000,1 ≤ w ≤ N,1 ≤ s ≤ 10000,1 ≤ c ≤ 100。
思路:先根据取钥匙的时间排序,然后再根据还钥匙的时间排序,如果还钥匙的时间相同,按照提示,先把编号小的钥匙换回去,检测放钥匙的数组,只要空就能放回去。代码完全按照提示的思路,排完序后先还钥匙(按序号小优先),然后再借钥匙。
import java.util.ArrayList; import java.util.Scanner; public class CCF201709_2 { public static class Teacher { public int key; public int start_time; public int time; public int return_time; Teacher(int key, int start_time, int time) { this.key = key; this.start_time = start_time; this.time = time; this.return_time = start_time + time; } public int getKey(int nowtime) { if (nowtime == start_time) { return key; } else { return 0; } } public int returnKey(int nowtime) { if (nowtime == return_time) { return key; } else { return 0; } } } public static void main(String[] args) { Scanner sc = new Scanner(System.in); int N = sc.nextInt(); int K = sc.nextInt(); ArrayList al_get = new ArrayList(); int endTime = 0; for (int i = 0; i < K; i++) { Teacher teacher = new Teacher(sc.nextInt(), sc.nextInt(), sc.nextInt()); if (teacher.return_time > endTime) { endTime = teacher.return_time; } al_get.add(teacher); } for (int i = 0; i < K; i++) { for (int j = 0; j < K - i - 1; j++) { Teacher teacher1 = (Teacher) al_get.get(j); Teacher teacher2 = (Teacher) al_get.get(j + 1); if (teacher1.start_time > teacher2.start_time) { int tempKey = teacher1.key; int tempStart_time = teacher1.start_time; int tempTime = teacher1.time; int tempReturn_time = teacher1.return_time; teacher1.key = teacher2.key; teacher1.start_time = teacher2.start_time; teacher1.time = teacher2.time; teacher1.return_time = teacher2.return_time; teacher2.key = tempKey; teacher2.start_time = tempStart_time; teacher2.time = tempTime; teacher2.return_time = tempReturn_time; } } } ArrayList al_return = al_get; for (int i = 0; i < K; i++) { for (int j = 0; j < K - i - 1; j++) { Teacher teacher1 = (Teacher) al_return.get(j); Teacher teacher2 = (Teacher) al_return.get(j + 1); if (teacher1.return_time > teacher2.return_time) { swap(teacher1, teacher2); continue; } if (teacher1.return_time == teacher2.return_time) { if (teacher1.key > teacher2.key) { swap(teacher1, teacher2); continue; } } } } int[] Key = new int[N + 1]; for (int i = 0; i < N + 1; i++) { Key[i] = i; } for (int nowtime = 1; nowtime <= endTime; nowtime++) { for (int j = 0; j < K; j++) { Teacher teacher = (Teacher) al_return.get(j); if (teacher.returnKey(nowtime) != 0) { for (int i = 1; i < N + 1; i++) { if (Key[i] == 0) { Key[i] = teacher.returnKey(nowtime); break; } } } } for (int j = 0; j < K; j++) { Teacher teacher = (Teacher) al_get.get(j); if (teacher.getKey(nowtime) != 0) { for (int i = 1; i < N + 1; i++) { if (Key[i] == teacher.key) { Key[i] = 0; break; } } } } } for (int i = 1; i < N + 1; i++) { System.out.print(Key[i] + " "); } } public static void swap(Teacher teacher1, Teacher teacher2) { int tempKey = teacher1.key; int tempStart_time = teacher1.start_time; int tempTime = teacher1.time; int tempReturn_time = teacher1.return_time; teacher1.key = teacher2.key; teacher1.start_time = teacher2.start_time; teacher1.time = teacher2.time; teacher1.return_time = teacher2.return_time; teacher2.key = tempKey; teacher2.start_time = tempStart_time; teacher2.time = tempTime; teacher2.return_time = tempReturn_time; } }
试题编号:201712-1
试题名称:最小差值
样例输入
5
1 5 4 8 20
样例输出
1
样例说明
相差最小的两个数是5和4,它们之间的差值是1。
样例输入
5
9 3 6 1 3
样例输出
0
样例说明
有两个相同的数3,它们之间的差值是0.
数据规模和约定
对于所有评测用例,2 ≤ n ≤ 1000,每个给定的整数都是不超过10000的正整数。
思路:先排序,然后比较相邻,记录最小
import java.util.Arrays; import java.util.Scanner; public class CCF201712_1 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int[] A = new int[n]; for (int i = 0; i < n; i++) { A[i] = sc.nextInt(); } Arrays.sort(A, 0, A.length); int min = A[1] - A[0]; for (int i = 1; i < n; i++) { if ((A[i] - A[i - 1]) < min) { min = A[i] - A[i - 1]; } } System.out.println(min); } }
试题编号:201712-2
试题名称:游戏
样例输入
5 2
样例输出
3
样例输入
7 3
样例输出
4
数据规模和约定
对于所有评测用例,1 ≤ n ≤ 1000,1 ≤ k ≤ 9。
思路:约瑟夫环问题,因为需要经常删除元素,所以使用LinkedList速度会快一点,就是一个下标的循环,分开判断即可简单解决。
import java.util.LinkedList; import java.util.Scanner; public class CCF201712_2 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int k = sc.nextInt(); if (n == 1) { System.out.println(1); return; } LinkedList ll = new LinkedList(); for (int i = 1; i < n + 1; i++) { ll.add(i); } int count = 1; int index = 0; while (ll.size() > 1) { if ((count % k == 0) || (count % 10 == k)) { ll.remove(index); count++; if (index == ll.size()) { index = 0; } continue; } if (index == ll.size() - 1) { index = 0; } else { index++; } count++; } System.out.println(ll.get(0)); } }
试题编号:201803-1
试题名称:跳一跳
样例输入
1 1 2 2 2 1 1 2 2 0
样例输出
22
数据规模和约定
对于所有评测用例,输入的数字不超过30个,保证0正好出现一次且为最后一个数字。
思路:比较2的时候通过一个单独的参数去增加得分倍数即可,发现下一次不是2时,再把这个单独的参数初始化即可。
import java.util.Scanner; public class CCF201803_1 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int temp = sc.nextInt(); int ret = temp; int last = temp; int prise = 2; while (temp != 0) { temp = sc.nextInt(); if (temp == 0) { continue; } if (temp == 1) { if (last == 2) {// 1的上一个是2,终结了,重新刷新 prise = 2; } ret += 1; last = 1; continue; } if (last == 2) { prise += 2; } ret += prise; last = 2; } System.out.println(ret); } }
试题编号:201803-2
试题名称:碰撞的小球
样例输入
3 10 5
4 6 8
样例输出
7 9 9
思路:模拟题,一直觉得这种题挺有意思的,但这题不复杂,主要就是一个撞墙(与墙下标重叠)互撞(与另一个球下标重叠)方向和速度也很简单,一秒一秒模拟即可。
但是因为最后需要按小球序号输出,需要单独记录一下num
import java.util.ArrayList; import java.util.Scanner; public class CCF201803_2 { public static class Ball { public int num; public int index; public int direction = 1; public int flag = 1; public Ball(int num, int index) { this.num = num; this.index = index; } public Ball() { this.num = 0; this.index = 0; } public void changeFinded() { flag *= -1; } public void changeDirection() { direction *= -1; } public void step() { index += direction; } } public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int L = sc.nextInt(); int t = sc.nextInt(); ArrayList al = new ArrayList(); for (int i = 1; i <= n; i++) { Ball ball = new Ball(i, sc.nextInt()); al.add(ball); } for (int i = 0; i < t; i++) { for (int j = 0; j < n; j++) { Ball ball1 = (Ball) al.get(j); if (ball1.index == L) {// 检测是否撞墙 ball1.changeDirection(); } for (int k = 0; k < n; k++) { Ball ball2 = (Ball) al.get(k); if (ball2.index == ball1.index) {// 下标重复 if (ball2.flag == 1 && ball1.flag == 1) {// 第一次遇到 if (ball2.num != ball1.num) {// 并且不是同一颗球 ball1.changeDirection(); ball1.changeFinded(); ball2.changeDirection(); ball2.changeFinded(); break; } } else {// 第二次遇到改flag,但不操作 ball1.changeFinded(); ball2.changeFinded(); break; } } } } for (int j = 0; j < n; j++) { Ball ball1 = (Ball) al.get(j); ball1.step(); } } for (int i = 0; i < n; i++) { for (int j = 0; j < n - i - 1; j++) { Ball ball1 = (Ball) al.get(j); Ball ball2 = (Ball) al.get(j + 1); if (ball1.num > ball2.num) { int tempNum = ball1.num; int tempIndex = ball1.index; ball1.num = ball2.num; ball1.index = ball2.index; ball2.num = tempNum; ball2.index = tempNum; } } } for (int i = 0; i < n; i++) { Ball ball = (Ball) al.get(i); System.out.print(ball.index + " "); } } }
试题编号:201809-1
试题名称:卖菜
样例输入
8
4 1 3 1 6 5 17 9
样例输出
2 2 1 3 4 9 10 13
数据规模和约定
对于所有评测用例,2 ≤ n ≤ 1000,第一天每个商店的菜价为不超过10000的正整数。
思路:很简单,第一个和最后一个(n,下标n-1)分开判断,其他的与相邻就好,考虑特殊情况,2个店,1个店即可。
import java.util.Scanner; public class CCF201809_1 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n=sc.nextInt(); int[] A=new int[n]; for(int i=0;i<n;i++) { A[i]=sc.nextInt(); } if(n==2) { System.out.print((A[0]+A[1])/2+" "); System.out.print((A[0]+A[1])/2); return; } for(int i=0;i<n;i++) { if(i==0) { System.out.print((A[i]+A[i+1])/2+" "); continue; } if(i==n-1) { System.out.print((A[i-1]+A[i])/2+" "); break; } System.out.print((A[i-1]+A[i]+A[i+1])/3+" "); } } }
试题编号:201809-2
试题名称:买菜
样例输入
4
1 3
5 6
9 13
14 15
2 4
5 7
10 11
13 14
样例输出
3
数据规模和约定
对于所有的评测用例,1 ≤ n ≤ 2000, ai < bi < ai+1,ci < di < ci+1,对于所有的i(1 ≤ i ≤ n)有,1 ≤ ai, bi, ci, di ≤ 1000000。
思路:用hashset的去重功能,只要插入的时候返回了false,就说明已经有人在那里了,就可以过去聊天。
import java.util.HashSet; import java.util.Scanner; public class CCF201809_2 { public static void main(String[] args) { Scanner sc=new Scanner(System.in); int n=sc.nextInt(); HashSet hs=new HashSet(); int x=0; int y=0; int ret=0; for(int i=0;i<n*2;i++) { x=sc.nextInt(); y=sc.nextInt(); for(int j=x;j<y;j++) { if(hs.add(j)==false) { ret++; } } } System.out.println(ret); } }
试题编号:201812-1
试题名称:小明上学
样例输入
30 3 30
8
0 10
1 5
0 11
2 2
0 6
0 3
3 10
0 3
样例输出
70
样例说明
小明先经过第一段道路,用时 10 秒,然后等待 5 秒的红灯,再经过第二段道路,用时 11 秒,然后等待 2 秒的黄灯和 30 秒的红灯,再经过第三段、第四段道路,分别用时6、3秒,然后通过绿灯,再经过最后一段道路,用时 3 秒。共计 10 + 5 + 11 + 2 + 30 + 6 + 3 + 3=70 秒。
评测用例规模与约定
测试点 1, 2 中不存在任何信号灯。
测试点 3, 4 中所有的信号灯在被观察时均为绿灯。
测试点 5, 6 中所有的信号灯在被观察时均为红灯。
测试点 7, 8 中所有的信号灯在被观察时均为黄灯。
测试点 9, 10 中将出现各种可能的情况。
思路:去计算当前时间落在的区间范围即可。
import java.util.Scanner; public class CCF201812_1 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); Long r=sc.nextLong(); Long y=sc.nextLong(); Long g=sc.nextLong(); int n=sc.nextInt(); Long[][] A=new Long[n][2]; int ret=0; for(int i=0;i<n;i++) { A[i][0]=sc.nextLong(); A[i][1]=sc.nextLong(); if(A[i][0]==0) { ret+=A[i][1]; continue; } if(A[i][0]==1) { ret+=A[i][1]; continue; } if(A[i][0]==2) { ret+=A[i][1]+r; continue; } if(A[i][0]==3) { if(A[i][1]==0) { ret+=r+y; } continue; } } System.out.println(ret); } }
试题编号:201812-2
试题名称:小明放学
样例输入
30 3 30
8
0 10
1 5
0 11
2 2
0 6
0 3
3 10
0 3
样例输出
46
样例说明
小明先经过第一段路,用时 10 秒。第一盏红绿灯出发时是红灯,还剩 5 秒;小明到达路口时,这个红绿灯已经变为绿灯,不用等待直接通过。接下来经过第二段路,用时 11 秒。第二盏红绿灯出发时是黄灯,还剩两秒;小明到达路口时,这个红绿灯已经变为红灯,还剩 11 秒。接下来经过第三、第四段路,用时 9 秒。第三盏红绿灯出发时是绿灯,还剩 10 秒;小明到达路口时,这个红绿灯已经变为红灯,还剩两秒。接下来经过最后一段路,用时 3 秒。共计 10+11+11+9+2+3 = 46 秒。
评测用例规模与约定
有些测试点具有特殊的性质:
* 前 2 个测试点中不存在任何信号灯。
测试点的输入数据规模:
* 前 6 个测试点保证 n ≤ 103。
* 所有测试点保证 n ≤ 105。
思路:有一个比第一题更好的思路,就是不去计算剩余时间,用当前区间减去剩余时间,去计算初始时间,然后加上总的经过时间,在去折算区间,问题会变得简单的多。这一题在完成转化之后,与上一题情况类似,所以不粘贴代码了,仅提供思路。