第七届蓝桥杯(2016年)JavaB组省赛真题解析

第七届蓝桥杯(2016年)JavaB组省赛真题解析

  • 1.煤球数量
  • 有一堆煤球,堆成三角棱锥形
  • 第一层1个
  • 第二层3个
  • 第三层6个
  • 第四层10个
  • 如果有100层,一共有多少个煤球?
/**
 * 1.煤球数量
 * 有一堆煤球,堆成三角棱锥形
 * 第一层1个
 * 第二层3个
 * 第三层6个
 * 第四层10个
 * ...
 * 如果有100层,一共有多少个煤球?
 */
public class Main {
    public static void main(String[] args) {
        int level = 0, sum = 0 ;
        for(int i=1; i<=100; i++){
            level  += i ;
            sum += level ;
        }
        System.out.println(sum);
    }
}

2.生日蜡烛

public class Main {
    public static void main(String[] args) {

        for(int i=1;i<100; i++){
            int sum = 0 ;
            for(int j=i;j<100; j++){
                sum += j;
                if(sum == 236){
                    System.out.println(i);
                    break ;
                }else if(sum > 236){
                    continue;
                }
            }
        }
    }
}

3.凑算式

public class Main {
    static int cnt = 0 ;
    static int [] arr = new int [] {1,2,3,4,5,6,7,8,9} ;
    public static void main(String[] args) {
        f(arr, 0) ;
        System.out.println(cnt);
    }

    private static void f(int[] arr, int k) {
        if(k == arr.length){
            if(check()){
                cnt ++ ;
            }
        }
        for(int j=k; j<arr.length; j++){
            swap(arr, j, k) ;
            f(arr, k+1) ;
            swap(arr, j, k) ;
        }
    }

    private static boolean check() {
        int A = arr[0] ;
        int B = arr[1] ;
        int C = arr[2] ;
        int DEF = arr[3]*100+arr[4]*10+arr[5] ;
        int GHI = arr[6]*100+arr[7]*10+arr[8] ;
        if(A + 1.0*B/C + 1.0*DEF/GHI == 10){
            return true ;
        }
        return false ;
    }

    private static void swap(int []arr, int j, int k){
        int temp = arr[j] ;
        arr[j] = arr[k] ;
        arr[k] = temp ;
    }
}

4,5填空题略

6.方格填数

public class Main {
    static int cnt = 0 ;
    static int [] arr = new int [] {0,1,2,3,4,5,6,7,8,9} ;
    public static void main(String[] args) {
        f(arr, 0) ;
        System.out.println(cnt);
    }

    private static void f(int[] arr, int k) {
        if(k == arr.length){
            if(check()){
                cnt ++ ;
            }
        }
        for(int j=k; j<arr.length; j++){
            swap(arr, j, k) ;
            f(arr, k+1) ;
            swap(arr, j, k) ;
        }
    }

    private static boolean check() {
      if(Math.abs(arr[0]-arr[1])==1 || Math.abs(arr[1]-arr[2])==1){
          return false ;
      }
      if(Math.abs(arr[3]-arr[4])==1 || Math.abs(arr[4]-arr[5])==1 || Math.abs(arr[5]-arr[6])==1){
          return false ;
      }
      if(Math.abs(arr[7]-arr[8])==1 || Math.abs(arr[8]-arr[9])==1){
          return false ;
      }
      if(Math.abs(arr[0]-arr[4])==1 || Math.abs(arr[1]-arr[5])==1 || Math.abs(arr[2]-arr[6])==1){
          return false ;
      }
      if(Math.abs(arr[3]-arr[7])==1 || Math.abs(arr[4]-arr[8])==1 || Math.abs(arr[5]-arr[9])==1){
          return false ;
      }
      if(Math.abs(arr[0]-arr[3])==1 || Math.abs(arr[1]-arr[4])==1 || Math.abs(arr[5]-arr[2])==1){
            return false ;
      }
        if(Math.abs(arr[4]-arr[7])==1 || Math.abs(arr[5]-arr[8])==1 || Math.abs(arr[6]-arr[9])==1){
            return false ;
        }
        if(Math.abs(arr[0]-arr[5])==1 || Math.abs(arr[1]-arr[6])==1){
            return false ;
        }
        if(Math.abs(arr[3]-arr[8])==1 || Math.abs(arr[4]-arr[9])==1){
            return false ;
        }
      return true ;
    }

    private static void swap(int []arr, int j, int k){
        int temp = arr[j] ;
        arr[j] = arr[k] ;
        arr[k] = temp ;
    }
}

7.剪邮票

方法1:先全排列,再去重,再搜索判断是否联通,
最后统计联通的个数就是我们的答案。

/**
 * 先全排列,再去重,在搜索判断是否联通
 * 最后统计联通的个数就是我们的答案,
 * 这个时间复杂度过高,运行时间较长
 */

import java.util.Set;
import java.util.TreeSet;

public class Main {
    static int cnt = 0 ;
    static int [] arr = new int [] {0,0,0,0,0,0,0,1,1,1,1,1} ;
    static  int [][] res ;
    static Set<String> set = new TreeSet<>() ;
    public static void main(String[] args) {
        f(arr, 0) ;
        System.out.println(cnt);
    }

    private static void f(int[] arr, int k) {
        if(k == arr.length){
            if(check() && check1()) {
                    cnt++;
            }
        }
        for(int j=k; j<arr.length; j++){

            swap(arr, j, k) ;
            f(arr, k+1) ;
            swap(arr, j, k) ;
        }
    }

    private static boolean check1() {
        int size = set.size() ;
        String s = "" ;
        for(int i=0; i<arr.length; i++){
            s += arr[i] ;
        }
        set.add(s) ;
        if(set.size() > size){
            return true ;
        }else{
            return false ;
        }
    }

    private static boolean check() {
        res = new int [3][4] ;

     for(int i=0; i<3; i++){
         for(int j=0; j<4; j++){
             res[i][j] = arr[i*4+j] ;
         }
     }
     int num = 0 ;
     for(int i=0; i<3; i++){
         for(int j=0; j<4; j++){
             if(res[i][j] == 1){
                 dfs( i, j) ;
                 num ++ ;
                 }
             }
         }
     return num==1 ;
    }

    private static void dfs(int x, int y) {
        res[x][y] = 0;
        if(x-1>=0 && res[x-1][y]==1){
            dfs(x-1, y) ;
        }
        if(x+1<=2 && res[x+1][y]==1){
            dfs( x+1, y) ;
        }
        if(y-1>=0 && res[x][y-1]==1){
            dfs( x, y-1) ;
        }
        if(y+1<=3 && res[x][y+1]==1){
            dfs( x , y+1) ;
        }
    }

    private static void swap(int []arr, int j, int k){
        int temp = arr[j] ;
        arr[j] = arr[k] ;
        arr[k] = temp ;
    }
}

方法2:抓取法提前去重,再搜索判断是否联通

public class Main1 {
    static int [] a = {0,0,0,0,0,0,0,1,1,1,1,1} ;
    static int cnt = 0 ;
    static boolean [] vis = new boolean[12] ;
    static int [] path = new int [12] ;
    public static void main(String[] args) {
        full(0) ;
        System.out.println(cnt);
    }

    private static void full(int k) {
        if(k == path.length){
            if(checks()) {
                cnt++;
            }
        }
        for(int j=0; j<path.length; j++){
            //抓取法提前去重,得到非重复的
            if(j>0 && a[j]==a[j-1] && !vis[j-1]){
                continue;
            }
            if(!vis[j]){
                vis[j] = true ;
                path[k] = a[j] ;
                full(k+1) ;
                vis[j] = false ;
            }
        }
    }

    private static boolean checks() { //判断联通
        int [][] g = new int [3][4] ;
        for(int i=0; i<3; i++){
            for(int j=0; j<4; j++){
                g[i][j] = path[i*4+j] ;
            }
        }
        int num = 0 ;
        for(int i=0; i<3; i++){
            for(int j=0; j<4; j++){
                if(g[i][j] == 1){
                    dfs1(g, i, j) ;
                    num ++ ;
                }
            }
        }
        return num==1 ;
    }

    private static void dfs1(int[][] g, int i, int j) {
        g[i][j] = 0 ;
        if(i-1>=0 && g[i-1][j]==1){
            dfs1(g, i-1, j) ;
        }
        if(i+1<=2 && g[i+1][j]==1){
            dfs1(g, i+1, j) ;
        }
        if(j-1>=0 && g[i][j-1]==1){
            dfs1(g, i, j-1) ;
        }
        if(j+1<=3 && g[i][j+1]==1){
            dfs1(g, i, j+1) ;
        }
    }
}

8.四平方和

方法1:暴力枚举

/**
 * 这一题暴力法也可以拿满分,
 * 因为找到第一个立刻就结束遍历了,
 * 不需要找出所有的,所以不会超时
 */

import java.util.Scanner;

public class Main {
    static int n ;
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in) ;
        n = input.nextInt() ;
        for(int i=0; i<=Math.sqrt(n/4); i++){
            for(int j=i; j<=Math.sqrt(n/3); j++){
                for(int k=j; k<=Math.sqrt(n/2); k++){
                    for(int l=k; l<=Math.sqrt(n); l++){
                        if(n == (i*i + j*j + k*k + l*l)){
                            System.out.println(i + " " + j + " " + k + " " + l);
                            return ;
                        }
                    }
                }
            }
        }
    }
}

方法2:枚举优化

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class Main1 {
    static int n ;
    static Map<Integer, Integer> map = new HashMap<>() ;
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in) ;
        n = input.nextInt() ;
        for(int c=0; c*c<=n/2; c++){
            for(int d=c; c*c+d*d<=n; d++){
                if(map.get(c*c + d*d) == null){
                    map.put(c*c+d*d, c) ;
                }
            }
        }
        for(int a=0; a*a<=n/4; a++){
            for(int b=a; a*a+b*b<=n/2; b++){
                if(map.get(n - a*a - b*b) != null){
                    int c = map.get(n-a*a-b*b) ;
                    int d = (int)Math.sqrt(n - a*a - b*b - c*c) ;
                    System.out.println(a + " " + b + " "+ c + " " + d );
                    return ;
                }
            }
        }
    }
}

9.取球博弈
方法一:按数量判断的记忆性递归


import java.util.Arrays;
import java.util.Scanner;

/**
 * 这题是标准的博弈问题,而不是贪心问题
 * 我们可以进行试探,每一次其实是有至多三种句面,
 * 我们选其中一种,然后交给对手,三种句面中只要出现对手输,
 * 则我们赢,如果存在平局,则平局,否则我们输。
 */
public class Main1 {
    static int [] n ;
    static char [][][] cache ;
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in) ;
        n = new int [3] ;
        cache = new char [1000][1000][1000] ;
        for(int i=0; i<n.length; i++){
            n[i] = input.nextInt() ;
        }
        Arrays.sort(n) ;
        for(int i=0; i<5; i++){
            int num = input.nextInt() ;
            char res = game(num, 0, 0) ;
            System.out.print(res + " ");
        }
    }

    private static char game(int num, int me, int you) {
        if(num < n[0]){
            if((me&1)==1 &&(you&1)==0){
                return '+' ;
            }else if((me&1)==0 &(you&1)==1){
                return '-' ;
            }else{
                return '0' ;
            }
        }
        if(cache[num][me][you] != '\0'){
            return cache[num][me][you] ;
        }
        boolean flag = false ;
        for(int i=0; i<n.length; i++){
            if(num >= n[i]){
                char res = game(num-n[i], you, me+n[i]) ;
                if(res == '-'){
                    cache[num][me][you] = '+' ;
                    return '+' ;
                }
                if(res == '0'){
                    flag = true ;
                }
            }
        }
        if(flag){
            cache[num][me][you] = '0' ;
            return '0' ;
        }else{
            cache[num][me][you] = '-' ;
            return '-' ;
        }
    }
}

方法2:按奇偶判断的记忆性递归

import java.util.Arrays;
import java.util.Scanner;

/**
 * 这题是标准的博弈问题,而不是贪心问题
 * 我们可以进行试探,每一次其实是有至多三种句面,
 * 我们选其中一种,然后交给对手,三种句面中只要出现对手输,
 * 则我们赢,如果存在平局,则平局,否则我们输。
 */
public class Main2 {
    static int [] n ;
    static char [][][] cache ;
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in) ;
        n = new int [3] ;
        cache = new char [1000][1000][1000] ;
        for(int i=0; i<n.length; i++){
            n[i] = input.nextInt() ;
        }
        Arrays.sort(n) ;
        for(int i=0; i<5; i++){
            int num = input.nextInt() ;
            char res = game(num, 0, 0) ;
            System.out.print(res + " ");
        }
    }

    private static char game(int num, int me, int you) {
        if(num < n[0]){
            if((me&1)==1 &&(you&1)==0){
                return '+' ;
            }else if((me&1)==0 &(you&1)==1){
                return '-' ;
            }else{
                return '0' ;
            }
        }
        if(cache[num][me][you] != '\0'){
            return cache[num][me][you] ;
        }
        boolean flag = false ;
        for(int i=0; i<n.length; i++){
            if(num >= n[i]){
                char res = game(num-n[i], you, (n[i]&1)==0 ? me : 1-me) ;
                if(res == '-'){
                    cache[num][me][you] = '+' ;
                    return '+' ;
                }
                if(res == '0'){
                    flag = true ;
                }
            }
        }
        if(flag){
            cache[num][me][you] = '0' ;
            return '0' ;
        }else{
            cache[num][me][you] = '-' ;
            return '-' ;
        }
    }
}


10.压缩变换
方法1:HashMap存储,set去重法


/**
 * 10.压缩变换
 *
 */
import java.util.*;

public class Main {
    static int n ;
    static int [] a ;
    static int [] res ;
    static Map<Integer, Integer> map = new HashMap<>() ;
    static Set<Integer> set = new TreeSet<>() ;
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in) ;
        n = input.nextInt() ;
        a = new int [n] ;
        res = new int [n] ;

        for(int i=0; i<n; i++){
            a[i] = input.nextInt() ;
            if(map.get(a[i])==null){
                res[i] = -a[i] ;
            }else{
                for(int j=map.get(a[i])+1; j<i; j++){
                    set.add(a[j]) ;
                }
                res[i] = set.size() ;
                set.clear();
            }
            map.put(a[i], i) ;
        }
        for(int i=0; i<res.length; i++){
            System.out.print(res[i] + " ");
        }
    }
}

方法2:线段树法


import java.util.*;

public class Main1 {
    static int n ;
    static int [] a ;
    static int [] res ;
    static Map<Integer, Integer> map = new HashMap<>() ;
    static SegTree root ;
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in) ;
        n = input.nextInt() ;
        a = new int [n] ;
        res = new int [n] ;
        root = buildSegTree(0, n-1) ;

        for(int i=0; i<n; i++){
            a[i] = input.nextInt() ;
            if(map.get(a[i])==null){
                res[i] = -a[i] ;
                //更新线段树
                update(root, i, 1) ;
            }else{
                //区间和
                res[i] = query(root, map.get(a[i])+1, i-1) ;
                //更新线段树
                update(root, i, 1) ;
                update(root, map.get(a[i]), -1);
            }
            map.put(a[i], i) ;
        }
        for(int i=0; i<res.length; i++){
            System.out.print(res[i] + " ");
        }
    }

    private static int query(SegTree root, int x, int y) {
        int l = root.l ;
        int r = root.r ;
        if(x <= l && y>=r){
            return root.sum ;
        }
        int mid = (l+r)>>1 ;
        int ans = 0 ;
        if(x<=mid){
            ans += query(root.lson, x, y) ;
        }
        if(y > mid){
            ans += query(root.rson, x, y) ;
        }
        return ans ;
    }

    private static void update(SegTree root, int x, int y) {
        if(root == null){
            return ;
        }
        int l = root.l ;
        int r = root.r ;
        root.sum += y ;
        int mid = (l+r)>>1 ;
        if(x<=mid){
            update(root.lson, x, y);
        }else{
            update(root.rson, x, y);
        }
    }

    private static SegTree buildSegTree(int l, int r) {
        SegTree segTree = new SegTree(l, r) ;
        if(l == r){
            segTree.sum = 0 ;
            return segTree ;
        }
        int mid = (l+r) >> 1 ;
        SegTree lson = buildSegTree(0, mid) ;
        SegTree rson = buildSegTree(mid+1, r) ;
        segTree.lson = lson ;
        segTree.rson = rson ;
        return  segTree ;
    }
    static class SegTree{
        int l, r ;
        int sum ;
        SegTree lson ;
        SegTree rson ;
        public SegTree(int l, int r){
            this.l = l ;
            this.r = r ;
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

nuist__NJUPT

给个鼓励吧,谢谢你

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

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

打赏作者

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

抵扣说明:

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

余额充值