第八届蓝桥杯(2017年)JavaA组省赛真题解析

第八届蓝桥杯(2017年)JavaA组省赛真题解析

  • 1.迷宫
  • X星球的一处迷宫游乐园建在某个小山坡上,
  • 它是由10*10相互联通的小房间组成,房间的地板上写着很大的字母,
  • 我们假设玩家是面超着上坡的方向战立,则
  • L表示走到左边的房间
  • R表示走到右边的额房间
  • U表示走向上坡方向的房间
  • D表示走到下坡方向的房间
  • 100位玩家,你算一下最后又有多少个能走出迷宫?

方式1:搜索+标记


public class Main {
    static int cnt = 0 ;
    static int [][] vis = new int [10][10] ;
    public static void main(String[] args) {
        char[][] a = {
                {'U','D','D','L','U','U','L','R','U','L'},
                {'U','U','R','L','L','L','R','R','R','U'},
                {'R','R','U','U','R','L','D','L','R','D'},
                {'R','U','D','D','D','D','U','U','U','U'},
                {'U','R','U','D','L','L','R','R','U','U'},
                {'D','U','R','L','R','L','D','L','R','L'},
                {'U','L','L','U','R','L','L','R','D','U'},
                {'R','D','L','U','L','L','R','D','D','D'},
                {'U','U','D','D','U','D','U','D','L','L'},
                {'U','L','R','D','L','U','U','R','R','R'},

        };

        for(int i=0; i<10; i++){
            for(int j=0; j<10; j++){
               boolean res =  dfs(a, i, j) ;
               if(res){
                   cnt ++ ;
                   clear(vis) ;
               }
            }
        }
        System.out.println(cnt);
    }

    private static void clear(int[][] vis) {
        for(int i=0; i<vis.length; i++){
            for(int j=0; j<vis[0].length; j++){
                vis[i][j] = 0 ;
            }
        }
    }

    private static boolean dfs(char[][] a, int i, int j) {
        if(i<0 || j<0 || i>9 || j>9){
            return true ;
        }
        if(vis[i][j] == 1){
            return false ;
        }
        vis[i][j] = 1 ;
     switch (a[i][j]){
         case 'U': return dfs(a, i-1, j) ;
         case 'D': return dfs(a, i+1, j) ;
         case 'L': return dfs(a, i, j-1) ;
         case 'R': return dfs(a, i, j+1) ;
         default: return  false ;
     }
    }
}

方式2:

/**
 * 1.迷宫
 * X星球的一处迷宫游乐园建在某个小山坡上,
 * 它是由10*10相互联通的小房间组成,房间的地板上写着很大的字母,
 * 我们假设玩家是面超着上坡的方向战立,则
 * L表示走到左边的房间
 * R表示走到右边的额房间
 * U表示走向上坡方向的房间
 * D表示走到下坡方向的房间
 * 100位玩家,你算一下最后又有多少个能走出迷宫?
 */
public class Main1 {
    static int cnt = 0 ;
    static int [][] vis = new int [10][10] ;
    public static void main(String[] args) {
        char[][] a = {
                {'U','D','D','L','U','U','L','R','U','L'},
                {'U','U','R','L','L','L','R','R','R','U'},
                {'R','R','U','U','R','L','D','L','R','D'},
                {'R','U','D','D','D','D','U','U','U','U'},
                {'U','R','U','D','L','L','R','R','U','U'},
                {'D','U','R','L','R','L','D','L','R','L'},
                {'U','L','L','U','R','L','L','R','D','U'},
                {'R','D','L','U','L','L','R','D','D','D'},
                {'U','U','D','D','U','D','U','D','L','L'},
                {'U','L','R','D','L','U','U','R','R','R'},

        };

        for(int i=0; i<10; i++){
            for(int j=0; j<10; j++){
                 dfs(a, i, j) ;

            }
        }
        System.out.println(cnt);
    }

    private static void clear(int[][] vis) {
        for(int i=0; i<vis.length; i++){
            for(int j=0; j<vis[0].length; j++){
                vis[i][j] = 0 ;
            }
        }
    }

    private static void dfs(char[][] a, int i, int j) {
        if(i<0 || j<0 || i>9 || j>9){
            cnt ++ ;
            clear(vis);
            return ;
        }
        if(vis[i][j] == 1){
            clear(vis);
            return ;
        }
        vis[i][j] = 1 ;
        if(a[i][j] == 'U'){
            dfs(a, i-1, j) ;
        }
        if(a[i][j] == 'D'){
            dfs(a, i+1, j) ;
        }
        if(a[i][j] == 'L'){
            dfs(a, i, j-1) ;
        }
        if(a[i][j] == 'R'){
            dfs(a, i, j+1) ;
        }
    }
}


  1. 9数算式
    全排列划分区间计算
/**
 * 9数算式
 */

import java.util.Arrays;
public class Main {
    //最后要除2
    static int [] a ;
    static int cnt = 0 ;
    public static void main(String[] args) {
        a = new int[] {1,2,3,4,5,6,7,8,9} ;
        f(a, 0) ;
        System.out.println(cnt/2);
    }

    private static void f(int[] a, int k) { //全排列
        if(k==a.length){
            check(a) ;
        }
        for(int j=k; j<a.length; j++){
            swap(a, j, k) ;
            f(a, k+1) ;
            swap(a, j, k) ;
        }
    }

    private static void swap(int [] a, int i, int j){
        int temp = a[i] ;
        a[i] = a[j] ;
        a[j] = temp ;
    }
    private static  void check(int [] a) { //第每个排列判断,并计数
            for(int j=1; j<a.length; j++){
                int pre = compute(a, 0, j) ;
                int pos = compute(a, j, a.length) ;
                int value = pre * pos ;
                if(judge(value)){
                    cnt ++ ;
                }
        }
    }

    private static int compute(int[] a, int x, int y) {
        int sum = 0 ;
        for(int i=x; i<y; i++){
            sum = sum * 10 + a[i] ;
        }
        return sum ;
    }

    private static boolean judge(int value) {
        String s = String.valueOf(value);
        char [] r = s.toCharArray() ;
        Arrays.sort(r);
        String s1 = String.valueOf(r) ;
       return s1.equals("123456789") ;
    }
}

3.魔方状态

  • 4.方格分割
  • 6*6的方格,沿着格子的边线剪成两部分,要求这两部分完全相同,
  • 一共有多少种分割方法,旋转对称的属于同一种方法。
/**
 * 4.方格分割
 * 6*6的方格,沿着格子的边线剪成两部分,要求这两部分完全相同,
 * 一共有多少种分割方法,旋转对称的属于同一种方法。
 *
 */
public class Main {
    static int cnt = 0 ;
    static int [] offsetX = {-1,1,0,0} ;
    static int [] offsetY = {0,0,-1,1} ;
    static int [][] vis  = new int [7][7] ;
    public static void main(String[] args) {
        dfs(3, 3) ;
        System.out.println(cnt/4);
    }

    private static void dfs(int x, int y) {
        if(x==0 || y==0 || x==6 || y==6){
            cnt ++ ;
            return ;
        }
        vis[x][y] = 1 ;
        vis[6-x][6-y] = 1 ;
        for(int i=0; i<4; i++){
            int nx = offsetX[i] + x ;
            int ny = offsetY[i] + y ;
            if(nx<0 || ny<0 || nx>6 || ny>6){
                continue;
            }
            if(vis[nx][ny] != 1){
                dfs(nx, ny);
            }
        }
        vis[x][y] = 0 ;
        vis[6-x][6-y] = 0 ;

    }
}

5,6代码填空,略

  • 7.正则问题
  • 考虑一种简单的正则表达式,只有x()|组成的正则表达式,
  • 小明想求出这个正则表达式能接受的最长字符串的长度。
  • 输入正则表达式,输出这个正则表达式能接收的最长字符串的长度。
import java.util.Scanner;

/**
 * 7.正则问题
 * 考虑一种简单的正则表达式,只有x()|组成的正则表达式,
 * 小明想求出这个正则表达式能接受的最长字符串的长度。
 * 输入正则表达式,输出这个正则表达式能接收的最长字符串的长度。
 *
 */
public class Main {
    static String s ;
    static int cnt = 0 ;
    static  int len ;
    static int pos = 0 ;
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in) ;
        s = input.next() ;
        len = s.length() ;
        cnt = f() ;
        System.out.println(cnt);
    }

    private static int f() {
        int temp = 0 ; //保存连续的x数量
        int m = 0;
       while(pos < len){
           if(s.charAt(pos) == '('){
               pos ++ ;
               temp += f() ; //等待结果,并累加到cnt
           }else if(s.charAt(pos) == 'x'){
               pos ++ ;
               temp ++ ;
           }else if(s.charAt(pos) == '|'){
               pos ++ ;
               m = Math.max(m, temp) ;
               temp = 0 ;
           }else if(s.charAt(pos) == ')'){
               pos ++ ;
               m = Math.max(m, temp) ;
               return m ;
           }
       }
       m = Math.max(m, temp);
       return m ;
    }
}

  • 8.包子凑数
import java.util.Scanner;

/**

 */
public class Main {
    static int n ;
    static int [] a ;
    static int cnt = 0 ;
    static int g ;
    static boolean [] f = new boolean[10000] ;
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in) ;
        n = input.nextInt() ;
        f[0] = true ;
        a = new int [n] ;
        for(int i=0; i<n; i++){
            a[i] = input.nextInt() ;
            if(i==0){
                g = a[i] ;
            }else{
                g = gcd(g, a[i]) ;
            }
            for(int j=0; j+a[i]<10000; j++){
                if(f[j]){
                    f[j+a[i]] = true ;
                }
            }
        }
        if(g!=1){
            System.out.println("INF");
        }else {
            for(int i=0; i<10000; i++){
                if(!f[i]){
                    cnt ++ ;
                    //System.out.println(i);
                }
            }
            System.out.println(cnt);
        }
    }

    private static int gcd(int m, int n) {
        if(n == 0){
            return m ;
        }else{
            return gcd(n, m%n) ;
        }
    }
}

/**

  • 9.分巧克力
  • 儿童节会有K位小朋友到小明家里做客,小明拿出珍藏的巧克力招待小朋友们,
  • 小明一共有N块巧克力,其中第i块是Hi×Wi的方格组成的长方形。
  • 小明需要从N块巧克力中切出K块分给小朋友,切出的巧克力要满足:
  • 1.形状是正方形,边长是整数
  • 2.大小相同
  • 例如一块6×5的巧克力可以切除6块2×2的巧克力或者2块3×3的巧克力。

*/
方法1:暴力枚举法



import java.util.Scanner;

/**
 * 方法1:暴力枚举法
 */
public class Main {
    static int N, K, cnt = 0 ;
    static int [] H ;
    static int [] W ;
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in) ;
        N = input.nextInt() ;
        K = input.nextInt() ;
        H = new int [N] ;
        W = new int [N] ;
        for(int i=0; i<N; i++){
            H[i] = input.nextInt() ;
            W[i] = input.nextInt() ;
        }
        int len = 100000 ;
        for(int i=len;i>=1 ; i--){
            for(int j=0; j<N; j++) {
                cnt += (H[j] / i) * (W[j] / i) ;
            }
            if(cnt >= K){
                System.out.println(i);
                break ;
            }
        }
    }
}

方法2:二分法优化暴力枚举

import java.util.Scanner;

public class Main1 {
    static int N ,  K, cnt = 0 ;
    static int [] H ;
    static int [] W ;
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in) ;
        N = input.nextInt() ;
        K = input.nextInt() ;
        H = new int [N] ;
        W = new int [N] ;
        for(int i=0; i<N; i++){
            H[i] = input.nextInt() ;
            W[i] = input.nextInt() ;
        }
        int l = 1, r = 100001 ;
        while(l<=r){ //二分法优化暴力枚举
            int mid = (l+r)>>1 ;
            int sum = 0 ;
            for(int i=0; i<N; i++){
                sum += (H[i] / mid) * (H[i] / mid) ;
            }
            if(sum >= K){
                l = mid + 1 ;
                cnt = mid ;
            }else{
                r = mid - 1 ;
            }
        }
        System.out.println(cnt);
    }
}

  • 10.油漆面积
  • 矩阵的格式表示为(x1,y1,x2,y2),代表两个矩阵的对角点坐标
  • 所有机器人选中的矩形区域涂上黄色油漆,
  • 计算一下,一共耗费多少油漆,只需要计算所有矩形的覆盖面积有多大就可以
  • 注意:各个矩形可能会重叠。
  • 要求:输入为若干矩阵,输出为面积总和。
  • 输入:
  • 3
  • 1 5 10 10
  • 3 1 20 20
  • 2 7 15 17
  • 输出:
  • 340
    *输入:
  • 3
  • 5 2 10 6
  • 2 7 12 10
  • 8 1 15 15
  • 输出:
  • 128

扫描标记法:

import java.util.Scanner;


public class Main {
    static int n, cnt = 0 ;
    static boolean [][] vis = new boolean[10000][10000] ;
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in) ;
        n = input.nextInt() ;
        for(int i=0; i<n; i++){
            int x1 = input.nextInt() ;
            int y1 = input.nextInt() ;
            int x2 = input.nextInt() ;
            int y2 = input.nextInt() ;
            for(int j=x1; j<x2; j++){
                for(int k=y1; k<y2; k++){
                    vis[j][k] = true ;
                }
            }
        }
        for(int i=0; i<10000;i++){
            for(int j=0; j<10000; j++){
                if(vis[i][j]){
                    cnt ++ ;
                }
            }
        }
        System.out.println(cnt);
    }
}

线段树+扫描线法

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

nuist__NJUPT

给个鼓励吧,谢谢你

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值