每日省赛真题解析·第八天
每日省赛真题解析·第八天

每日省赛真题解析·第八天

目录

  • 2019省赛试题E
  • 2019省赛试题F
  • 2019省赛试题G

一.2019省赛试题E

maze.txt文件内容如下

01010101001011001001010110010110100100001000101010
00001000100000101010010000100000001001100110100101
01111011010010001000001101001011100011000000010000
01000000001010100011010000101000001010101011001011
00011111000000101000010010100010100000101100000000
11001000110101000010101100011010011010101011110111
00011011010101001001001010000001000101001110000000
10100000101000100110101010111110011000010000111010
00111000001010100001100010000001000101001100001001
11000110100001110010001001010101010101010001101000
00010000100100000101001010101110100010101010000101
11100100101001001000010000010101010100100100010100
00000010000000101011001111010001100000101010100011
10101010011100001000011000010110011110110100001000
10101010100001101010100101000010100000111011101001
10000000101100010000101100101101001011100000000100
10101001000000010100100001000100000100011110101001
00101001010101101001010100011010101101110000110101
11001010000100001100000010100101000001000111000010
00001000110000110101101000000100101001001000011101
10100101000101000000001110110010110101101010100001
00101000010000110101010000100010001001000100010101
10100001000110010001000010101001010101011111010010
00000100101000000110010100101001000001000000000010
11010000001001110111001001000011101001011011101000
00000110100010001000100000001000011101000000110011
10101000101000100010001111100010101001010000001000
10000010100101001010110000000100101010001011101000
00111100001000010000000110111000000001000000001011
10000001100111010111010001000110111010101101111000

题目链接:迷宫 – 蓝桥云课 (lanqiao.cn)

题目要求:

本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。

下图给出了一个迷宫的平面图,其中标记为 1 的为障碍,标记为 0 的为可以通行的地方。

010000
000100
001001
110000

迷宫的入口为左上角,出口为右下角,在迷宫中,只能从一个位置走到这 个它的上、下、左、右四个方向之一。

对于上面的迷宫,从入口开始,可以按 DRRURRDDDR 的顺序通过迷宫, 一共 10 步。其中 D、U、L、R 分别表示向下、向上、向左、向右走。 对于下面这个更复杂的迷宫(30 行 50 列),请找出一种通过迷宫的方式,其使用的步数最少,在步数最少的前提下,请找出字典序最小的一个作为答案。请注意在字典序中 D<L<R<U。

解题思路:

本题是一道简单的搜索题,需要注意的是要按照题目给定的字典序进行搜索,最后输出路径。

我们使用 BFS 搜索记录路径,用 DFS 打印路径。

代码:

import java.util.*;
public class Main {
    private static String[] nn= {
                  "01010101001011001001010110010110100100001000101010",
                  "00001000100000101010010000100000001001100110100101",
                  "01111011010010001000001101001011100011000000010000",
                  "01000000001010100011010000101000001010101011001011",
                  "00011111000000101000010010100010100000101100000000",
                  "11001000110101000010101100011010011010101011110111",
                  "00011011010101001001001010000001000101001110000000",
                  "10100000101000100110101010111110011000010000111010",
                  "00111000001010100001100010000001000101001100001001",
                  "11000110100001110010001001010101010101010001101000",
                  "00010000100100000101001010101110100010101010000101",
                  "11100100101001001000010000010101010100100100010100",
                  "00000010000000101011001111010001100000101010100011",
                  "10101010011100001000011000010110011110110100001000",
                  "10101010100001101010100101000010100000111011101001",
                  "10000000101100010000101100101101001011100000000100",
                  "10101001000000010100100001000100000100011110101001",
                  "00101001010101101001010100011010101101110000110101",
                  "11001010000100001100000010100101000001000111000010",
                  "00001000110000110101101000000100101001001000011101",
                  "10100101000101000000001110110010110101101010100001",
                  "00101000010000110101010000100010001001000100010101",
                  "10100001000110010001000010101001010101011111010010",
                  "00000100101000000110010100101001000001000000000010",
                  "11010000001001110111001001000011101001011011101000",
                  "00000110100010001000100000001000011101000000110011",
                  "10101000101000100010001111100010101001010000001000",
                  "10000010100101001010110000000100101010001011101000",
                  "00111100001000010000000110111000000001000000001011",
                  "10000001100111010111010001000110111010101101111000"};
    private static char[][] tu=new char[30][50];
    private static int[][] dis=new int[30][50];
    private static int[][] step= {{1,0},{0,-1},{0,1},{-1,0}};
    private static char[] direction= {'D','L','R','U'};
//    保存经过的每一个点位置信息,采用(x)*m+y的公式表示(x,y);x,y从0开始,位置也是从来开始。m:大于最长边的随便一个数
//    起点:0;终点:29*50-49
    private static Queue<Integer> location=new LinkedList<Integer>();
//    广度优先遍历求每一个位置到终点的距离,并存放在dis中
//    广度优先遍历寻找所有从终点到起点的路线
    public static void bfs() {//x,y当前位置;
        int x,y;//当前位置坐标
        //不为空,继续循环
        while(!location.isEmpty()) {
            int l=location.poll();//获取当前位置的坐标
            x=l/50;//获取当前位置x
            y=l%50;//获取当前位置y
            for(int i=0;i<4;i++) {//探索四个方向
                int xx=x+step[i][0];
                int yy=y+step[i][1];
                if(xx>=0&&xx<30&&yy>=0&&yy<50&&tu[xx][yy]=='0'&&dis[xx][yy]==0) {
                    dis[xx][yy]=dis[x][y]+1;//当前位置的距离+1等于本次探索位置的距离
                    location.add(xx*50+yy);
                    if(xx==0&&yy==0) {
                        break;
                    }
                }
            }

        }
    }
//    深度优先遍历,从起点到终点
    public static String dfs() {
        dis[29][49]=0;
//        起点
        int x=0;
        int y=0;
        String route="";
        while(x!=29||y!=49) {
            for(int i=0;i<4;i++) {
                int xx=x+step[i][0];
                int yy=y+step[i][1];
                if(xx>=0&&xx<30&&yy>=0&&yy<50&&tu[xx][yy]=='0') {
                    if(dis[x][y]==dis[xx][yy]+1) {
                        x=xx;
                        y=yy;
                        route+=direction[i];
                        break;
                    }
                }
            }
        }
        return route;
    }

    public static void main(String[] args) {
        long num=0;
        for(int i=0;i<30;i++) {
            tu[i]=nn[i].toCharArray();
        }
        location.add(29*50+49);
        bfs();
        String route=dfs();
        System.out.println(route);
    }
}

二.2019省赛试题F

题目链接:特别数的和 – 蓝桥云课 (lanqiao.cn)

题目要求:

小明对数位中含有 2、0、1、9 的数字很感兴趣(不包括前导 0),在 1 到 40 中这样的数包括 1、2、9、10 至 32、39 和 40,共 28 个,他们的和是 574。请问,在 1 到 n 中,所有这样的数的和是多少?

解题思路:

本题是比较简单的暴力题目,直接暴力枚举 1 到 n 中所有数字,对每个数字进行数位判断,找出含有特定数位的数字进行相加即可。

代码:

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        long sum = 0;
        for (int i = 1; i <= n; i++) {
            if (cheak(i)) {
                sum += i;
            }
        }
        System.out.println(sum);
        sc.close();
    }

    private static boolean cheak(int n) {
        while (n != 0) {
            int a = n % 10;
            if (a == 2 || a == 0 || a == 1 || a == 9) {
                return true;
            }
            n /= 10;
        }
        return false;
    }
}

三.2019省赛试题G

题目链接:外卖店优先级 – 蓝桥云课 (lanqiao.cn)

题目要求:

“饱了么”外卖系统中维护着 N 家外卖店,编号 1 ∼ N。每家外卖店都有 一个优先级,初始时 (0 时刻) 优先级都为 0。每经过 1 个时间单位,如果外卖店没有订单,则优先级会减少 1,最低减 到 0;而如果外卖店有订单,则优先级不减反加,每有一单优先级加 2。如果某家外卖店某时刻优先级大于 5,则会被系统加入优先缓存中;如果 优先级小于等于 3,则会被清除出优先缓存。给定 T 时刻以内的 M 条订单信息,请你计算 T 时刻时有多少外卖店在优 先缓存中?

解题思路:

代码:

import java.util.Scanner;

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

public class Main
{
    public static void main(String[] args)
    {
        int N,M,T;
        Scanner in = new Scanner(System.in);
        N=in.nextInt()+1;
        M=in.nextInt();
        T=in.nextInt();
        Order[] order=new Order[M];
        for(int x=0;x<M;x++)
        {
            order[x]=new Order(in.nextInt(),in.nextInt());
        }
        //这个用来记录上一次last[x],x这家订单的时间T
        int[] last=new int[N];
        //保存每个店的分数
        int[] score=new int[N];

        //保存每家店是否在优先队列之中
        boolean[] isPriority=new boolean[N];

        Arrays.sort(order);
        for(int x=0;x<M;)
        {
            int y=x;
            //寻找这家店这个时间有多少单订单
            while(y<M && order[x].id==order[y].id && order[x].time==order[y].time)
            {
                y++;
            }
            //记录当前店的id和time
            int id=order[x].id;
            int time=order[x].time;
            int sum=y-x;
            //将y赋值给x,y是下一个店的订单或者是下一个时间的订单
            x=y;
            //less是这家店相隔多少时间没有订单了
            int less=time-last[id]-1;
            //多久没有订单就要减少相应的分数
            score[id] -=less;
            if(score[id]<0)
            {
                score[id]=0;
            }
            if(score[id]<=3)
            {
                isPriority[id]=false;
            }
            //下面是要加分的,如果达到要求就进去优先队列
            score[id] +=sum*2;
            if(score[id]>5)
            {
                isPriority[id]=true;
            }
            //保存当前店的最后的订单时间
            last[id]=time;
        }
        /*
         * 因为后面还有可能就是还没到T的时间,但是某些店已经没有订单了
         * 后面的每一个时间段都是要扣分的
         */
        for(int x=0;x<N;x++)
        {
            int less=T-last[x];
            score[x] -=less;
            if(score[x]<=3)
            {
                isPriority[x]=false;
            }
        }
        int count=0;
        for (boolean b : isPriority)
        {
            if(b)
            {
                count++;
            }
        }
        System.out.println(count);
    }

}
class Order implements Comparable<Order>
{
    public int time;
    public int id;
    public Order(int time, int id)
    {
        super();
        this.time = time;
        this.id = id;
    }
    @Override
    public int compareTo(Order o)
    {
        if(this.time==o.time)
        {
            if(this.id==o.id)
            {
                return 0;
            }
            return this.id>o.id?1:-1;
        }
        return this.time>o.time?1:-1;
    }
}