2018年第九届蓝桥杯国赛试题及详解(Java本科B组)

1. 三角形面积

已知三角形三个顶点在直角坐标系下的坐标分别为:
(2.3, 2.5)
(6.4, 3.1)
(5.1, 7.2)

求该三角形的面积。

注意,要提交的是一个小数形式表示的浮点数。
要求精确到小数后3位,如不足3位,需要补零。

解析:

求三角形面积,用这个三角形的外接矩形减去三个直角三角形的面积

package A;

public class Main {
    public static void main(String[] args) {
        double a = 5.1 - 2.3;
        double b = 7.2 - 2.5;
        double sumA = (a*b) / 2.0;
        
        double c = 6.4 - 2.3;
        double d = 3.1 - 2.5;
        double sumB = c*d / 2.0;
        
        double e = 7.2 - 3.1;
        double f = 6.4 - 5.1;
        double sumC = e*f / 2.0;
        
        double sum = b*c;
        
        System.out.println(sum - sumA - sumB - sumC);
    }
}

我的答案:8.795

2. 最大乘积

把 1~9 这9个数字分成两组,中间插入乘号,
有的时候,它们的乘积也只包含1~9这9个数字,而且每个数字只出现1次。

比如:

984672 * 351 = 345619872
98751 * 3462 = 341875962
9 * 87146325 = 784316925
...

符合这种规律的算式还有很多,请你计算在所有这些算式中,乘积最大是多少?

注意,需要提交的是一个整数,表示那个最大的积,不要填写任何多余的内容。
(只提交乘积,不要提交整个算式)

解析:

比较常规的搜索题,因为n比较小,所以可以搜出所有情况,最后再判断满足条件的解

package B;

import java.util.HashSet;

public class Main {
    static int[] a = new int[15];
    static boolean[] vis = new boolean[15];
    static long max = 0, maxa, maxb;
    
    static int num(int[] t, int start, int end) {
        // 给定开始和结束的下标, 左闭右开
        int sum = 0;
        for (int i = start; i < end; i++) {
            sum = sum*10 + t[i];
        }
        return sum;
    }
    
    static boolean judge(long n) {
        HashSet<Long> hs = new HashSet<Long>();
        while(n != 0) {
            if (n % 10 == 0) return false;
            hs.add(n % 10);
            n /= 10;
        }
        if (hs.size() == 9) {
            return true;
        } else {
            return false;    
        }
        
    }
    
    static void dfs(int n) {
        if (n == 9) {
            // 乘号的位置
            for (int i = 1; i < 9; i++) {
                int ta = num(a, 0, i);
                int tb = num(a, i, 9);
                long sum = ta * tb;
                if (judge(sum) && sum > max) {
                    max = sum;
                    maxa = ta;
                    maxb = tb;
                }
                
            }
            return ;
        }
        
        for (int i = 1; i <= 9; i++) {
            if (vis[i] == false) {
                vis[i] = true;
                a[n] = i;
                dfs(n+1);
                vis[i] = false;
            }
        }
    }
    public static void main(String[] args) {
        dfs(0);
        System.out.println(maxa + "*" + maxb + "=" + max);
    }
}

我的答案:839542176

3. 全排列

仔细分析一下,全排列是交换的,回溯的过程应该就是上面写的for循环倒过来。

我的答案是:for (int j = cur; j <= i-1; j++) data[j] = data[j+1]

4. 整理玩具

标题:整理玩具

小明有一套玩具,一共包含NxM个部件。这些部件摆放在一个包含NxM个小格子的玩具盒中,每个小格子中恰好摆放一个部件。

每一个部件上标记有一个0~9的整数,有可能有多个部件标记相同的整数。

小明对玩具的摆放有特殊的要求:标记相同整数的部件必须摆在一起,组成一个矩形形状。

如以下摆放是满足要求的:

00022
00033
44444

12244
12244
12233

01234
56789

以下摆放不满足要求:

11122
11122
33311

111111
122221
122221
111111

11122
11113
33333

给出一种摆放方式,请你判断是否符合小明的要求。

输入

输入包含多组数据。
第一行包含一个整数T,代表数据组数。 (1 <= T <= 10)
以下包含T组数据。
每组数据第一行包含两个整数N和M。 (1 <= N, M <= 10)
以下包含N行M列的矩阵,代表摆放方式。

输出

对于每组数据,输出YES或者NO代表是否符合小明的要求。

【样例输入】
3
3 5
00022
00033
44444
3 5
11122
11122
33311
2 5
01234
56789

【样例输出】
YES
NO
YES

资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 1000ms

请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
不要使用package语句。不要使用jdk1.7及以上版本的特性。
主类的名字必须是:Main,否则按无效代码处理。

解析:

这道题我用的方法是模拟,因为数据范围也比较小

package D;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.HashSet;
import java.util.StringTokenizer;

public class Main {
    static InputReader in = new InputReader(new BufferedInputStream(System.in));
    static PrintWriter out = new PrintWriter(System.out);
    static String[] G = new String[105];
    static boolean[][] vis = new boolean[105][105];
    
    static void init(int n, int m) {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                vis[i][j] = false;
            }
        }
    }
    
    static boolean judgeRec(int x, int y, int width, int height, char ch) {
        // 判断(i, j)为左上角的长度width 高度height 是否为矩形
        for (int i = x; i <= x + height; i++) {
            for (int j = y; j <= y + width; j++) {
                vis[i][j] = true;
                if (G[i].charAt(j) != ch) {
                    return false;
                }
            }
        }
        return true;
    }
    
    public static void main(String[] args) {
        int t = in.nextInt();
        
        while(t-- > 0) {
            HashSet<Character> set = new HashSet<Character>();
            int n = in.nextInt();
            int m = in.nextInt();
            init(n, m);
            for (int i = 0; i < n; i++) {
                G[i] = in.readLine();
            }
            
            boolean flag = true;
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    if (vis[i][j] == false) {
                        // 出现重复的情况,就直接判断为不可以
                        char ch = G[i].charAt(j);
                        if (set.contains(ch)) {
                            flag = false;
                            break;
                        }
                        set.add(ch);
                        
                        // 计算出矩形的宽度
                        int width = 0, k = j;
                        while(k + 1 < m && G[i].charAt(k) == G[i].charAt(k+1)) {
                            width++;
                            k++;
                        }

                        // 计算矩形的高度
                        int height = 0;
                        k = i;
                        while(k + 1 < n && G[k].charAt(j) == G[k+1].charAt(j)) {
                            height++;
                            k++;
                        }
                        
                        if (!judgeRec(i, j, width, height, ch)) {
                            flag = false;
                            break;
                        }
                    }
                }
            }
            if (flag) {
                out.println("YES");    
            } else {
                out.println("NO");
            }
            out.flush();
        }
        
        out.close();
    }
    
    static class InputReader {
        public static BufferedReader br;
        public static StringTokenizer st;
        
        public InputReader(InputStream stream) {
            br = new BufferedReader(new InputStreamReader(stream), 32768);
            st = null;
        }
        
        public String next() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }
        
        public String readLine() {
            String s = null;
            try {
                s = br.readLine();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return s;
        }
        
        public int nextInt() {
            return Integer.parseInt(next());
        }
        
        public Long nextLong() {
            return Long.parseLong(next());
        }
        
        public Double nextDouble() {
            return Double.parseDouble(next());
        }
        
    }
}

5. 版本分支

标题:版本分支

小明负责维护公司一个奇怪的项目。这个项目的代码一直在不断分支(branch)但是从未发生过合并(merge)。
现在这个项目的代码一共有N个版本,编号1~N,其中1号版本是最初的版本。
除了1号版本之外,其他版本的代码都恰好有一个直接的父版本;即这N个版本形成了一棵以1为根的树形结构。

如下图就是一个可能的版本树:

    1
   / \
  2   3
  |  / \
  5 4   6

现在小明需要经常检查版本x是不是版本y的祖先版本。你能帮助小明吗?

输入

第一行包含两个整数N和Q,代表版本总数和查询总数。
以下N-1行,每行包含2个整数u和v,代表版本u是版本v的直接父版本。
再之后Q行,每行包含2个整数x和y,代表询问版本x是不是版本y的祖先版本。

对于30%的数据,1 <= N <= 1000 1 <= Q <= 1000
对于100%的数据,1 <= N <= 100000 1 <= Q <= 100000

输出

对于每个询问,输出YES或NO代表x是否是y的祖先。

【样例输入】
6 5
1 2
1 3
2 5
3 6
3 4
1 1
1 4
2 6
5 2
6 4

【样例输出】
YES
YES
NO
NO
NO

资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 1000ms

请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
不要使用package语句。不要使用jdk1.7及以上版本的特性。
主类的名字必须是:Main,否则按无效代码处理。

解析:

太菜了,只能暴力拿一部分分。

package E;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.StringTokenizer;

public class Main {
    static InputReader in = new InputReader(new BufferedInputStream(System.in));
    static PrintWriter out = new PrintWriter(System.out);
    static int n, q;
    static int[] pre = new int[100005];
    static boolean flag;

    static void check(int u, int v) {
        if (u == v) {
            flag = true;
            return ;
        }
        if (u == 1) {
            return ;
        }
        check(pre[u], v);
    }
    
    public static void main(String[] args) {
        n = in.nextInt();
        q = in.nextInt();
        
        for (int i = 0; i < n - 1; i++) {
            int a = in.nextInt();
            int b = in.nextInt();
            pre[b] = a;
        }
        
        for (int i = 0; i < q; i++) {
            flag = false;
            int a = in.nextInt();
            int b = in.nextInt();
            check(b, a);
            if (flag) {
                out.println("YES");
            } else {
                out.println("NO");
            }
            out.flush();
        }
        
        out.close();
    }
    
    static class InputReader {
        public static BufferedReader br;
        public static StringTokenizer st;
        
        public InputReader(InputStream stream) {
            br = new BufferedReader(new InputStreamReader(stream), 32768);
            st = null;
        }
        
        public String next() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }
        
        public String readLine() {
            String s = null;
            try {
                s = br.readLine();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return s;
        }
        
        public int nextInt() {
            return Integer.parseInt(next());
        }
        
        public Long nextLong() {
            return Long.parseLong(next());
        }
        
        public Double nextDouble() {
            return Double.parseDouble(next());
        }
        
    }
}
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值