CCF签到汇总(JAVA版本,2013-12~2018-12)

Posted stk0210

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CCF签到汇总(JAVA版本,2013-12~2018-12)相关的知识,希望对你有一定的参考价值。

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 ≤ wN, 1 ≤ s, c ≤ 30;
  对于60%的评测用例,1 ≤ N, K ≤ 50,1 ≤ wN,1 ≤ s ≤ 300,1 ≤ c ≤ 50;
  对于所有评测用例,1 ≤ N, K ≤ 1000,1 ≤ wN,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

 

思路:有一个比第一题更好的思路,就是不去计算剩余时间,用当前区间减去剩余时间,去计算初始时间,然后加上总的经过时间,在去折算区间,问题会变得简单的多。这一题在完成转化之后,与上一题情况类似,所以不粘贴代码了,仅提供思路。

以上是关于CCF签到汇总(JAVA版本,2013-12~2018-12)的主要内容,如果未能解决你的问题,请参考以下文章

CCF CSP个人题解汇总

基于jsp+mysql+java员工签到系统

CCF CSP历年一二题代码汇总

Redis位图

[国际A类会议] 2018最最最顶级的人工智能国际峰会汇总!CCF推荐!

IDEA+Java+Servlet+JSP+Mysql实现学生选课签到系统