蓝桥杯31天真题冲刺|题解报告|第二十五天

 大家好,我是snippet,今天是我们刷蓝桥真题的第二十五天,今天的内容包含搜索+贪心+动态规划,下面的我今天的题解

目录

一、全球变暖

题目链接:

全球变暖 - 蓝桥云课 (lanqiao.cn)

题目内容:

解题思路:

代码:

二、调手表

题目链接:调手表 - 蓝桥云课 (lanqiao.cn)

题目内容:

解题思路:

代码:

三、铺设道路

题目链接:铺设道路 - 蓝桥云课 (lanqiao.cn)

题目内容:

解题思路:

代码:

四、搬砖

题目链接:搬砖 - 蓝桥云课 (lanqiao.cn)

题目内容:

解题思路:

代码:


一、全球变暖

题目链接:

全球变暖 - 蓝桥云课 (lanqiao.cn)

题目内容:

题目描述

你有一张某海域 NxN 像素的照片,"."表示海洋、"#"表示陆地,如下所示:

.......

.##....

.##....

....##.

..####.

...###.

.......

其中"上下左右"四个方向上连在一起的一片陆地组成一座岛屿。例如上图就有 2 座岛屿。

由于全球变暖导致了海面上升,科学家预测未来几十年,岛屿边缘一个像素的范围会被海水淹没。具体来说如果一块陆地像素与海洋相邻(上下左右四个相邻像素中有海洋),它就会被淹没。

例如上图中的海域未来会变成如下样子:

.......

.......

.......

.......

....#..

.......

.......

请你计算:依照科学家的预测,照片中有多少岛屿会被完全淹没。

输入描述

第一行包含一个整数 N (1≤N≤1000)。

以下 N 行 N 列代表一张海域照片。

照片保证第 1 行、第 1 列、第 N 行、第 N 列的像素都是海洋。、

输出一个整数表示答案。

输入输出样例

示例

输入

7
.......
.##....
.##....
....##.
..####.
...###.
.......

输出

1

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 256M

解题思路:

代码:

package 蓝桥杯31天真题冲刺.Day25;

import java.io.*;

/**
 * @author snippet
 * @data 2023-03-28
 * 全球变暖-蓝桥云课
 */
// 搜索 dfs/bfs
public class T1_全球变暖 {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));

    static int n,sum,cnt;// n表示海域的长宽 sum表示岛屿的个数 cnt表示不会被完全淹没的岛屿的个数
    static boolean flag;// flag用来表示该岛屿是不是会被完全淹没 true表示不会 false表示会被完全淹没
    static int N = 1010;
    static char[][] c = new char[N][N];// 二维数组c存海域的组成 "."表示海洋 "#"表示陆地
    static boolean[][] visit = new boolean[N][N];// 二维数组visit表示这个位置是否被遍历过 false表示未被遍历 true表示遍历过了
    static int[] dx = {0, 0, 1, -1};
    static int[] dy = {1, -1, 0, 0};

    // 对每一片岛屿进行搜索
    static void dfs(int x, int y) {
        visit[x][y] = true;
        if (c[x+dx[0]][y+dy[0]] == '#' && c[x+dx[1]][y+dy[1]] == '#'
                && c[x+dx[2]][y+dy[2]] == '#' && c[x+dx[3]][y+dy[3]] == '#') flag = true;
        for (int i = 0; i < 4; i++) {
            int x1 = x + dx[i];
            int y1 = y + dy[i];
            if (x1 >= 0 && x1 < n && y1 >= 0 && y1 < n && c[x1][y1] == '#' && !visit[x1][y1]) {
                dfs(x1, y1);
            }
        }
    }

    public static void main(String[] args) throws IOException {
        String[] s = br.readLine().split(" ");
        n = Integer.parseInt(s[0]);
        for (int i = 0; i < n; i++) {
            s = br.readLine().split(" ");
            c[i] = s[0].toCharArray();
        }

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (c[i][j] == '#' && !visit[i][j]) {
                    flag = false;
                    sum++;
                    dfs(i, j);
                    // 如果这片岛屿不会被完全淹没,则cnt++
                    if (flag) cnt++;
                }
            }
        }
//        pw.println(sum + " " + cnt);
        pw.println(sum - cnt);
        pw.flush();
        br.close();
    }
}

二、调手表

题目链接:调手表 - 蓝桥云课 (lanqiao.cn)

题目内容:

题目描述

小明买了块高端大气上档次的电子手表,他正准备调时间呢。

在 M78 星云,时间的计量单位和地球上不同,M78 星云的一个小时有 n 分钟。

大家都知道,手表只有一个按钮可以把当前的数加一。在调分钟的时候,如果当前显示的数是 0 ,那么按一下按钮就会变成 1,再按一次变成 2 。如果当前的数是 n−1,按一次后会变成 0。

作为强迫症患者,小明一定要把手表的时间调对。如果手表上的时间比当前时间多 1,则要按 n−1 次加一按钮才能调回正确时间。

小明想,如果手表可以再添加一个按钮,表示把当前的数加 �k 该多好啊......

他想知道,如果有了这个 +k 按钮,按照最优策略按键,从任意一个分钟数调到另外任意一个分钟数最多要按多少次。

注意,按 +k 按钮时,如果加 k 后数字超过 n−1,则会对 n 取模。

比如,n=10,k=6 的时候,假设当前时间是 0,连按 2 次 +k 按钮,则调为 2。

输入描述

一行两个整数 n,k (0

输出描述

输出一行一个整数,表示按照最优策略按键,从一个时间调到另一个时间最多要按多少次。

输入输出样例

示例

输入

5 3

输出

2

样例解释

如果时间正确则按 0 次。否则要按的次数和操作系列之间的关系如下:

1:+1

2:+1, +1

3:+3

4:+3, +1

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 256M

解题思路:

代码:

package 蓝桥杯31天真题冲刺.Day25;

import java.io.*;
import java.util.LinkedList;
import java.util.Queue;

/**
 * @author snippet
 * @data 2023-03-28
 * 调手表-蓝桥云课
 */
public class T2_调手表 {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));

    static int n,k,max;
    static int N = 100100;
    static boolean[] visit = new boolean[N];
    static Queue queue = new LinkedList<>();

    public static void main(String[] args) throws IOException {
        String[] s = br.readLine().split(" ");
        n = Integer.parseInt(s[0]);
        k = Integer.parseInt(s[1]);
        queue.offer(0);
        visit[0] = true;
        while (!queue.isEmpty()) {
            int size = queue.size();
            max++;
            while (size-- > 0) {
                int x = queue.poll();
                if (!visit[(x + 1) % n]) {
                    visit[(x + 1) % n] = true;
                    queue.offer((x + 1) % n);
                }
                if (!visit[(x + k) % n]) {
                    visit[(x + k) % n] = true;
                    queue.offer((x + k) % n);
                }
            }
        }
        // 减去初始为0的时候
        pw.println(max - 1);
        pw.flush();
        br.close();
    }
}

三、铺设道路

题目链接:铺设道路 - 蓝桥云课 (lanqiao.cn)

题目内容:

题目描述

春春是一名道路工程师,负责铺设一条长度为 n 的道路。

铺设道路的主要工作是填平下陷的地表。整段道路可以看作是 n 块首尾相连的区域,一开始,第 i 块区域下陷的深度为 di​ 。

春春每天可以选择一段连续区间 [L,R],填充这段区间中的每块区域,让其下陷深度减少 1。在选择区间时,需要保证,区间内的每块区域在填充前下陷深度均不为 0 。

春春希望你能帮他设计一种方案,可以在最短的时间内将整段道路的下陷深度都变为 0 。

输入描述

输入包含两行,第一行包含一个整数 n,表示道路的长度。

第二行包含 n 个整数,相邻两数间用一个空格隔开,第 i 个整数为 di​ 。

其中,1≤n≤105,0≤di​≤104 。

输出描述

输出仅包含一个整数,即最少需要多少天才能完成任务。

输入输出样例

示例

输入

6
4 3 2 5 3 5

输出

9

样例解释

一种可行的最佳方案是,依次选择:[1,6]、[1,6]、[1,2]、[1,1]、[4,6]、[4,4]、[4,4]、[6,6]、[6,6]。

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 256M

解题思路:

代码:

package 蓝桥杯31天真题冲刺.Day25;

import java.io.*;

/**
 * @author snippet
 * @data 2023-03-28
 * 铺设道路-蓝桥云课
 */
// 贪心
public class T3_铺设道路 {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));

    static int n,ans;
    static int N = 100100;
    static int[] arr = new int[N];

    public static void main(String[] args) throws IOException {
        String[] s = br.readLine().split(" ");
        n = Integer.parseInt(s[0]);
        s = br.readLine().split(" ");
        for (int i = 1; i <= n; i++) {
            arr[i] = Integer.parseInt(s[i-1]);
        }
        // 贪心 --> 当该位置为0时 不可以跟其他位置一起填充
        // 那我们可以将每个位置往前减 如果该位置的下陷深度大于前一位置 那填充差值
        // 因为非差值可以通过前面的相同的值来填充
        for (int i = 1; i <= n; i++) {
            ans += Math.max(0, arr[i] - arr[i-1]);
        }
        pw.println(ans);
        pw.flush();
        br.close();
    }
}

四、搬砖

题目链接:搬砖 - 蓝桥云课 (lanqiao.cn)

题目内容:

问题描述

这天,小明在搬砖。

他一共有 n 块砖, 他发现第 i 砖的重量为 wi​, 价值为 vi​ 。他突然想从这些 砖中选一些出来从下到上堆成一座塔, 并且对于塔中的每一块砖来说, 它上面 所有砖的重量和不能超过它自身的价值。

他想知道这样堆成的塔的总价值(即塔中所有砖块的价值和)最大是多少。

输入格式

输入共 n+1 行, 第一行为一个正整数 n, 表示砖块的数量。

后面 n 行, 每行两个正整数 wi​,vi​ 分别表示每块砖的重量和价值。

输出格式

一行, 一个整数表示答案。

样例输入

5
4 4
1 1
5 2
5 5
4 3

样例输出

10

样例说明

选择第 1、2、4 块砖, 从上到下按照 2、1、4 的顺序堆成一座塔, 总价值 为 4+1+5=10

评测用例规模与约定

对于 20% 的数据, 保证 n≤10;

对于 100% 的数据, 保证 n≤1000;wi​≤20;vi​≤20000 。

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 512M

解题思路:

代码:

package 蓝桥杯31天真题冲刺.Day25;

import java.io.*;
import java.util.Arrays;
import java.util.Comparator;

/**
 * @author snippet
 * @data 2023-03-28
 * 搬砖-蓝桥云课
 */
// 动态规划+排序
public class T4_搬砖 {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));

    static int n,ans;
    static int N = 1010;
    static int[][] arr = new int[N][2];
    static int[] f = new int[N * 20];

    public static void main(String[] args) throws IOException {
        String[] s = br.readLine().split(" ");
        n = Integer.parseInt(s[0]);
        for (int i = 1; i <= n; i++) {
            s = br.readLine().split(" ");
            arr[i][0] = Integer.parseInt(s[0]);
            arr[i][1] = Integer.parseInt(s[1]);
        }
        Arrays.sort(arr,1,n+1, new Comparator() {
            @Override
            public int compare(int[] o1, int[] o2) {
                return (o1[0] + o1[1]) - (o2[0] + o2[1]);
            }
        });
        for (int i = 1; i <= n; i++) {
            int w = arr[i][0];
            int v = arr[i][1];
            for (int j = 20000; j >= w; j--) {
                if (v >= j - w) f[j] = Math.max(f[j], f[j - w] + v);
            }
        }
        for (int i = 0; i <= 20000; i++) {
            ans = Math.max(ans, f[i]);
        }
        pw.println(ans);
        pw.flush();
        br.close();
    }
}

你可能感兴趣的:(2023年蓝桥杯31天真题冲刺,蓝桥杯,算法,java)