第三次CCF计算机软件能力认证题目:(2014年12月14日)
题1 图书馆读者访问信息管理
【问题描述】
图书馆的读者有自己的读者编号,当读者访问图书馆时,能够返回读者第几次访问图书馆。
【输入格式】
第一行是整数N,表示接下来有N条读者访问记录需要处理。
第二行输入的是N条访问记录的读者的编号。
【输出格式】
输出一行,分别输出读者是第几次访问图书馆,输出以空格隔开。
【输入样例】
7
1 2 5 1 4 1 2
【输出样例】
1 1 1 2 1 3 2
【样例解释】
样例有七条读者访问记录,每次的读者编号分别是1,2,5,1,4,1,2;
输出的前三个是1,是表示读者1,2,5都是第一次访问图书馆,第四个输出2是表示读者编号为1的读者第二次访问,第五个输出是1,表示的是编号为4的读者第一次访问图书馆;第六个输出是编号为1的读者第三次访问图书馆;最后第七个输出2想必大家都懂了,表示编号为2的读者第二次访问图书馆。
第三次CCF计算机软件能力认证参考答案(java):1、图书馆读者访问信息管理
import java.util.*;
/**
* 3rd_CCF计算机软件能力认证题目(Java)1、图书馆读者访问次数管理
* @author http://weibo.com/wangmb007
* Edited 2014-12
*/
public class Main_CCF {
public static void main(String[] args) {
new Main_CCF().run();
}
public void run() {
final int Reader_Max = 10000; //读者人数设定,这里以一万为例.
Scanner fin = new Scanner(System.in);
int N = fin.nextInt();
int [] P_Data = new int[N];
int [][] Reader_Data = new int[Reader_Max][2]; //读者访问数据,含读者编号和读者第几次访问图书馆
for (int i = 0; i < Reader_Data.length; i++) {//读者数据的初始化
Reader_Data[i][0] = i; //读者编号
Reader_Data[i][1]=0; //读者访问次数
}
Scanner fin2 = new Scanner(System.in);
for (int i = 0; i < P_Data.length; i++) {
P_Data[i] = fin2.nextInt();
}
for (int i = 0; i < P_Data.length; i++) {
Reader_Data[P_Data[i]][1]++;
System.out.print(Reader_Data[P_Data[i]][1]+" ");
}
fin2.close();
fin.close();
}
}
测试输入输出结果:
5
1 2 3 2 2
1 1 1 2 3
题2 矩阵“Z”字形扫描输出
【问题描述】
在图像编码的算法中,需要将一个给定的方形矩阵进行Z字形扫描(Zigzag Scan)。给定一个n×n的矩阵,Z字形扫描的过程如下图所示:
对于下面的4×4的矩阵,
1 5 3 9
3 7 5 6
9 4 6 4
7 3 1 3
对其进行Z字形扫描后得到长度为16的序列:
1 5 3 9 7 3 9 5 4 7 3 6 6 4 1 3
请实现一个Z字形扫描的程序,给定一个n×n的矩阵,输出对这个矩阵进行Z字形扫描的结果。
输入格式
输入的第一行包含一个整数n,表示矩阵的大小。
输入的第二行到第n+1行每行包含n个正整数,由空格分隔,表示给定的矩阵。
输出格式
输出一行,包含n×n个整数,由空格分隔,表示输入的矩阵经过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的正整数。
【题2 题目来源 http://bbs.youkuaiyun.com/topics/390953265】
分析,建议再画出4阶的扫描图;
通过观察可以发现扫描时的主要动作可以分为三种,如上面我给出的示意图,一种是蓝色的“上行”;一种是红色的“下行”;一种是黄色的沿边界的。
继续观察如果发现这一题比较简单的突破口应该是行列和(i+j)的奇偶性,发现这点后就比较容易了。当i+j为奇数就“下行”,为偶数就“上行”。在边界位置的处理上面,不需要直接另外开始判断,因为【i+j的奇偶性就具有了完整性了】。在i+j的奇偶性前提下,边界考虑的条件可以适当筛选掉没有必要的判断,而使得最终的条件变得简洁!
下面就是我考试时候的原答案:
第三次CCF计算机软件能力认证参考答案(java):矩阵“Z”字形扫描输出
import java.util.*;
/**
* 3rd_CCF计算机软件能力认证题目(Java)2、方形矩阵进行Z字形扫描
* @author http://weibo.com/wangmb007
* Edited 2014-12
*/
public class Main_CCF {
public static void main(String[] args) {
new Main_CCF().run();
}
public void run() {
Scanner fin = new Scanner(System.in);
int N = fin.nextInt(); //N阶矩阵
int [][] matrix_N_N = new int[N][N]; //N阶矩阵
for(int i=0;i<N;i++){ //读取N阶matrix
fin = new Scanner(System.in);
for(int j=0;j<N;j++){
matrix_N_N[i][j] = fin.nextInt();
}
}
int i=0;
int j=0;
do {
System.out.print(matrix_N_N[i][j]+" ");
if ((i+j)%2 == 0) { //行列之和为偶数
if (i == 0 && j<(N-1)) {
j++;
}
else if (j == (N-1)){
i++;
}
else {
i--;j++;
}
} else {//行列之和为奇数
if (j == 0 && i<(N-1)) {
i++;
}
else if (i == (N-1)){
j++;
}
else {
i++;j--;
}
}
} while (i<N && j<N);
fin.close();
}
}
运行测试结果1:
4
1 2 3 4
5 6 7 8
9 8 7 6
0 1 2 3
1 2 5 9 6 3 4 7 8 0 1 7 8 6 2 3
运行测试结果2:
5
1 2 3 4 5
3 4 5 6 7
5 6 7 8 9
7 8 9 0 1
9 0 1 2 3
1 2 3 5 4 3 4 5 6 7 9 8 7 6 5 7 8 9 0 1 0 9 1 2 3
题3、题4、题5 待续。。。
。。。
。。。
更有往届试题样题,待续……【关于样题,CCF网上已有题目和答案(含C++)】
。。。
2014年首届CCF软件能力认证试题 答案探讨交流
题目1、求相反数个数
时间限制: 1 秒
空间限制: 256 MB
问题描述
有 N 个非零且各不相同的整数。请你编一个程序求出它们中有多少对相反数( a 和 − a 为一对相反数)。
输入格式
第一行包含一个正整数 N。 ( 1 ≤ N ≤ 500)。
第二行为 N 个用单个空格隔开的非零整数,每个数的绝对值不超过1000,保证这些整数各不相同。
输出格式
只输出一个整数,即这 N 个数中包含多少对相反数。
输入样例
5
1 2 3 -1 -2
输出样例
2
/**
* @author Fzu_Xmu_bmw http://weibo.com/wangmb007
* 求相反数个数 -Edited 2014-12-10
*/
import java.util.*;
public class Main {
public static void main(String[] args) {
new Main().run();
}
public void run() {
Scanner fin = new Scanner(System.in);
int Temp_Count = 0; //计数1
int N = fin.nextInt(); //返回键盘录入数据个数N,N不大于500
int[] count = new int[501];
for (int i = 0; i < N; i++) { //将N个数据数据存入数组中
count[i] = fin.nextInt();
}
int temp_result = 0;
for (int i = 0; i < N; i++) {
temp_result = count[i];
for (int j = 0; j < N; j++) {
if(count[j] == -temp_result){
Temp_Count++;
break;
}
}
}
System.out.println(Temp_Count/2);
fin.close();
}
}
题目2、窗口 (模拟点击窗口)
时间限制: 1 秒
空间限制: 256 MB
问题描述
在某图形操作系统中,有 N 个窗口,每个窗口都是一个两边与坐标轴分别平行的矩形区域。窗口的边界上的点也属于该窗口。窗口之间有层次的区别,在多于一个窗口重叠的区域里,只会显示位于顶层的窗口里的内容。
当你点击屏幕上一个点的时候,你就选择了处于被点击位置的最顶层窗口,并且这个窗口就会被移到所有窗口的最顶层,而剩余的窗口的层次顺序不变。如果你点击的位置不属于任何窗口,则系统会忽略你这次点击。
现在我们希望你写一个程序模拟点击窗口的过程。
输入格式
输入的第一行有两个正整数,即 N 和 M。( 1 ≤ N ≤ 10, 1 ≤ M ≤ 10)
接下来 N 行按照从最下层到最顶层的顺序给出 N 个窗口的位置。每行包含四个非负整数 x 1 , y1 , x 2 , y 2,表示该窗口的一对顶点坐标分别为( x 1 , y1) 和 ( x 2 , y 2)。保证 x 1 < x 2, y1 < y 2。
接下来 M 行每行包含两个非负整数 x, y,表示一次鼠标点击的坐标。
题目中涉及到的所有点和矩形的顶点的 x, y 坐标分别不超过 2559 和1439。
输出格式
输出包括 M 行,每一行表示一次鼠标点击的结果。如果该次鼠标点击选择了一个窗口,则输出这个窗口的编号(窗口按照输入中的顺序从 1 编号到 N);如果没有,则输出"IGNORED"(不含双引号)。
输入样例
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) 不属于任何窗口。
import java.util.*;
/**
* @author Fzu_Xmu_bmw http://weibo.com/wangmb007
* 模拟点击窗口 -Edited 2014-12-10
*/
public class Main {
public static void main(String[] args) {
new Main().run();
}
public void run() {
Scanner fin = new Scanner(System.in);
int N = fin.nextInt(); //N个窗口
int M = fin.nextInt(); //M个测试点
int [][] Win_Array = new int[N][4]; //保存窗口坐标的数组
int [] Mid = new int[4];
int [] Win_Order = new int[N]; //保存从底层到顶层的窗口
int [][] Dot_Array = new int[M][2];
for(int i=0;i<N;i++){ //读取窗口数据
Win_Order[i] = i+1;
fin = new Scanner(System.in);
for(int j=0;j<4;j++){
Win_Array[i][j] = fin.nextInt();
}
}
for(int i=0;i<M;i++){ //读取M个坐标点数据
fin = new Scanner(System.in);
for(int j=0;j<2;j++){
Dot_Array[i][j] = fin.nextInt();
}
}
for(int k=0;k<M;k++){//判断点是否在窗口上,判断窗口从最顶层开始,即每次从第N-1个窗口开始一次判断。
for(int i=N-1;i>=0;i--){
if(((Win_Array [i][0] <= Dot_Array[k][0] )&&(Dot_Array[k][0] <= Win_Array[i][2]))
&&
((Win_Array [i][1] <= Dot_Array[k][1] )&&(Dot_Array[k][1] <= Win_Array[i][3]))){
if(i<N-1){//调换第i个与第N-1个窗口【即交换二维数组第i行与第N-1行的数据】
int temp0 = i;
Mid = Win_Array [i];
for(int ii=0; ii<(N-1-i); ii++){
Win_Array [temp0] = Win_Array [temp0+1];
temp0++;
}
Win_Array [N-1] = Mid;
//同时保存窗口顺序
temp0 = i;
int Ex_Order = Win_Order[i];
for(int ii=0; ii<(N-1-i); ii++){
Win_Order [temp0] = Win_Order [temp0+1];
temp0++;
}
Win_Order [N-1] = Ex_Order;
}
System.out.println(Win_Order[N-1]);
break;
}
else if(i == 0)
System.out.println("IGNORED");
}
}
for(int i=0;i<N;i++){
for(int j=0;j<4;j++){
System.out.print(Win_Array[i][j]+"; ");
}
System.out.println(" ");
}
fin.close();
}
}
题三:问题描述
在一个定义了直角坐标系的纸上,画一个(x1,y1)到(x2,y2)的矩形指将横坐标范围从x1到x2,纵坐标范围从y1到y2之间的区域涂上颜色。
下图给出了一个画了两个矩形的例子。第一个矩形是(1,1) 到(4, 4),用绿色和紫色表示。第二个矩形是(2, 3)到(6, 5),用蓝色和紫色表示。图中,一共有15个单位的面积被涂上颜色,其中紫色部分被涂了两次,但在计算面积时只计算一次。在实际的涂色过程中,所有的矩形都涂成统一的颜色,图中显示不同颜色仅为说明方便。
给出所有要画的矩形,请问总共有多少个单位的面积被涂上颜色。
输入格式
输入的第一行包含一个整数n,表示要画的矩形的个数。
接下来n行,每行4个非负整数,分别表示要画的矩形的左下角的横坐标与纵坐标,以及右上角的横坐标与纵坐标。
输出格式
输出一个整数,表示有多少个单位的面积被涂上颜色。
样例输入
2
1 1 4 4
2 3 6 5
样例输出
15
评测用例规模与约定
1<=n<=100,0<=横坐标、纵坐标<=100。
以下是java参考源码:(依据约定开个100X100的数组,开始全置0,涂了就置1,最后统计1的个数)
//bmw007
import java.util.*;
public class Main_CCF {
public static void main(String[] args) {
new Main_CCF().run();
}
public void run() {
int [][] matrix_N_N = new int[100][100]; //定义100阶方矩阵
//默认开始是全部置0的,若不是就自己在此加入矩阵初始化。
int x1,y1,x2,y2,cnt=0;
Scanner fin = new Scanner(System.in);
int N = fin.nextInt();
int [][] matrix_N_4 = new int[N][4];
for (int i = 0; i < N; i++) {
for (int j = 0; j <4; j++) {
matrix_N_4[i][j] = fin.nextInt();
}
x1=matrix_N_4[i][0];
y1=matrix_N_4[i][1];
x2=matrix_N_4[i][2];
y2=matrix_N_4[i][3];
for (int k = x1; k < x2; k++) {//标记相应点
for (int w = y1; w < y2; w++) {
matrix_N_N[k][w]=1;
}
}
}
for (int i = 0; i < 100; i++) {//统计标志点的个数
for (int j = 0; j < 100; j++) {
if (matrix_N_N[i][j]==1) {
cnt++;
// System.out.print("("+i+","+j+");");
}
}
}
System.out.println(cnt); //打印结果
fin.close();
}
}
未完待续……^^