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

Posted Snippet~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了蓝桥杯31天真题冲刺|题解报告|第二十六天相关的知识,希望对你有一定的参考价值。

大家好,我是snippet,今天是刷蓝桥真题的第二十六天,今天的知识点包含搜索+动态规划,下面是我今天的题解

目录

一、玩具

题目链接:B-玩具_牛客小白月赛69 (nowcoder.com)

题目内容:

解题思路:

代码:

二、滑雪

题目链接:滑雪_牛客题霸_牛客网 (nowcoder.com)

题目内容:

解题思路:

代码:

三、abb

题目链接:abb_牛客题霸_牛客网 (nowcoder.com)

题目内容:

解题思路:

代码:

四、小红取数 

题目链接:小红取数_牛客题霸_牛客网 (nowcoder.com)

题目内容:

解题思路:

代码:


一、玩具

题目链接:B-玩具_牛客小白月赛69 (nowcoder.com)

题目内容:

题目描述:

有 n 个玩具,第 i 个玩具的价格是 ai​ 元,超市里搞促销活动,购买 2 个玩具即可免单其中价格较低的一个,价格相等也免单其中一个。牛牛想买下所有玩具,至少需要花多少元?

输入描述:

第一行一个正整数 n(1≤n≤10^6)。

第二行 n 个正整数,第 i 个表示 ai​(1≤ai​≤10^9)。

输出描述:

输出一行一个正整数,表示答案。

示例1

输入

3

1 2 3

输出

4

说明

第二个和第三个一起买,花 3 元,再花 1 元买下第一个,合计 4 元。

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

解题思路:

因为买玩具可以买一送一嘛,买贵的送便宜的 那我们就先从所有玩具中找到最贵的,买它 然后送只比它便宜的另外一个玩具 重复进行这个操作,就可以用最少的钱买这所有的玩具了

代码:

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

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

/**
 * @author snippet
 * @data 2023-03-29
 * 玩具-牛客网
 */
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;
    static long sum;
    static int N = 1000010;
    static long[] arr = new long[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 = 0; i < n; i++) 
            arr[i] = Long.parseLong(s[i]);
        
        Arrays.sort(arr, 0, n);

        for (int i = n-1; i >= 0; i-=2) 
            sum += arr[i];
        

        pw.println(sum);
        pw.flush();
        br.close();
    

二、滑雪

题目链接:滑雪_牛客题霸_牛客网 (nowcoder.com)

题目内容:

题目描述:

给定一个 n×m  的矩阵,矩阵中的数字表示滑雪场各个区域的高度,你可以选择从任意一个区域出发,并滑向任意一个周边的高度严格更低的区域(周边的定义是上下左右相邻的区域)。请问整个滑雪场中最长的滑道有多长?(滑道的定义是从一个点出发的一条高度递减的路线)。

(本题和矩阵最长递增路径类似,该题是当年NOIP的一道经典题)


数据范围: 1≤n,m≤100 ,矩阵中的数字满足 1≤val≤1000 

输入描述:

第一行输入两个正整数 n 和 m 表示矩阵的长宽。
后续 n 行输入中每行有 m 个正整数,表示矩阵的各个元素大小。

输出描述:

输出最长递减路线。

示例1

输入:

5 5

1 2 3 4 5

16 17 18 19 6

15 24 25 20 7

14 23 22 21 8

13 12 11 10 9

输出:

25

说明:

从25出发,每次滑向周边比当前小 1 的区域。 25->24->23->22->......->1

解题思路:

找到最长的递减的滑雪路径,我们可以使用dfs来对每个位置进行记忆化遍历搜索,如果它周围有高度比它低的区域,就对满足条件的区域进行递归遍历,每一条路递归遍历之后记得要回溯

代码:

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

import java.io.*;

/**
 * @author snippet
 * @data 2023-03-29
 * DP18_滑雪-牛客网
 */
// 记忆化搜索
public class T2_DP18_滑雪 
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));

    static int n,m,ans;
    static int N = 101;
    static int[][] arr = new int[N][N];
    static boolean[][] visit = new boolean[N][N];
    static int[] dx = 0, 0, 1, -1;
    static int[] dy = 1, -1, 0, 0;

    // 记忆化搜索
    static void dfs(int x, int y, int cnt) 
        // 每次遍历一个位置的时候都进行一次答案更新
        ans = Math.max(ans, cnt);
        // 标记遍历的位置
        visit[x][y] = 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 <= m && arr[x][y] > arr[x1][y1] && !visit[x1][y1]) 
                // 递归
                dfs(x1, y1, cnt+1);
            
        
        // 回溯
        visit[x][y] = false;
    

    public static void main(String[] args) throws IOException 
        String[] s = br.readLine().split(" ");
        n = Integer.parseInt(s[0]);
        m = Integer.parseInt(s[1]);
        for (int i = 1; i <= n; i++) 
            s = br.readLine().split(" ");
            for (int j = 1; j <= m; j++) 
                arr[i][j] = Integer.parseInt(s[j-1]);
            
        

        for (int i = 1; i <= n; i++) 
            for (int j = 1; j <= m; j++) 
                dfs(i, j, 1);
            
        
        pw.println(ans);
        pw.flush();
        br.close();
    

三、abb

题目链接:abb_牛客题霸_牛客网 (nowcoder.com)

题目内容:

题目描述

leafee 最近爱上了 abb 型语句,比如“叠词词”、“恶心心”

leafee 拿到了一个只含有小写字母的字符串,她想知道有多少个 "abb" 型的子序列?
定义: abb 型字符串满足以下条件:

1.字符串长度为 3 。

2.字符串后两位相同。

3.字符串前两位不同。

输入描述:

第一行一个正整数 n

第二行一个长度为 n 的字符串(只包含小写字母)

1≤n≤10^5

输出描述:

"abb" 型的子序列个数。

示例1

输入:

6

abcbcc

输出:

8

说明:

共有1个abb,3个acc,4个bcc

示例2

输入:

4

abbb

输出:

3

解题思路:

因为是求给定的字符串中只根据前后顺序来排子串,满足abb型的子串的个数(如果a,b,b字符一样,但是在字符串中的位置不一样,按不同种进行计算)

我最开始想到的是直接三层for循环进行遍历,因为数据范围是1≤n≤10^5,肯定会超时,没想到居然过了72.73%

根据题意,我们可以使用后缀和来求解,因为是求abb的串的个数,那我们就可以先给定a,然后求a后面的b的个数,那我们可以求每个位置数的后面字符的每个字符(a-z)的字符数和,然后我们对每个数进行遍历,再根据它的后缀和中每个字符的个数k来进行答案求和, ans += ki * (ki-1) / 2  (i=> [a, z]);(ka表示这个字符包括自己 后面的字符中含有a的个数)

代码:

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

import java.io.*;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;

/**
 * @author snippet
 * @data 2023-03-29
 * abb-牛客网
 */
public class T3_abb 
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));

    static int n;
    static long ans;
    static int N = 100010;
    static char[] c;
    static int[][] h = new int[N][26];// 二维数组h表示每个i后面的所有字母a-b的个数

    public static void main(String[] args) throws IOException 
        String[] s = br.readLine().split(" ");
        n = Integer.parseInt(s[0]);
        s = br.readLine().split(" ");
        c = s[0].toCharArray();
        int len = c.length;
        // 求后缀和
        // 列表示每个字母 行0-26表示这个字母以及后面的字母a-z的数的个数 存的数表示
        for (int i = len-1; i >= 0; i--) 
            char a = c[i];
            for (int j = 0; j < 26; j++) 
                h[i][j] = h[i+1][j];
            
            // 把自己加上
            h[i][a-'a']++;
        

        for (int i = 0; i < len; i++) 
            char a = c[i];
            for (int j = 0; j < 26; j++) 
                if (a - 'a' != j) 
                    ans += (long) h[i][j] * (h[i][j]-1) / 2;
                
            
        
        pw.println(ans);
        pw.flush();
        br.close();
    

//    // for循环 暴力求解 案例通过率:72.73%
//    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 char[] c;
//
//    public static void main(String[] args) throws IOException 
//        String[] s = br.readLine().split(" ");
//        n = Integer.parseInt(s[0]);
//        s = br.readLine().split(" ");
//        c = s[0].toCharArray();
//        int len = c.length;
//        for (int i = 0; i < len; i++) 
//            char a = c[i];
//            for (int j = i+1; j < len; j++) 
//                char b = c[j];
//                if (a != b) 
//                    for (int k = j+1; k < len; k++) 
//                        char d = c[k];
//                        if (a != b && b == d) ans++;
//                    
//                
//
//            
//        
//        pw.println(ans);
//        pw.flush();
//        br.close();
//    

四、小红取数 

题目链接:小红取数_牛客题霸_牛客网 (nowcoder.com)

题目内容:

题目描述:

小红拿到了一个数组,她想取一些数使得取的数之和尽可能大,但要求这个和必须是  k  的倍数。
你能帮帮她吗?

输入描述:

第一行输入两个正整数  n  和  k 

第二行输入  n  个正整数  ai​ 

1≤n,k≤10^3

1≤ai​≤10^10

输出描述:

如果没有合法方案,输出 -1。
否则输出最大的和。

示例1

输入:

5 5

4 8 2 9 1

复制输出:

20

说明:

取后四个数即可

解题思路:

因为我们要求给定的n个数中,任意取1至n个相加,组成的数x满足x%k == 0,求x的最大值,

那我们就可以使用二维dp对i个数中对k取余得到的每种情况进行状态转移,二维数组f[i][j]表示 每个数i与前面i个数中对k取模的值为j的最大值,f[n][0]也就是我们要求的最大的和

状态转移式:f[i][(j+arr[i])%k] = max(f[i-1][j] + arr[i], f[i-1][(j+arr[i])%k]);

代码:

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

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

/**
 * @author snippet
 * @data 2023-03-29
 * 小红取数-牛客网
 */
// 动态规划 二维dp
public class T4_DP40_小红取数 
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));

    static int n,k;
    static int N = 1010;
    static long[] arr = new long[N];
    static long[][] f = new long[N][N];// 二维数组f 行i表示前i个数 列表示这前i个数中%k的余数为j的最大值

    public static void main(String[] args) throws IOException 
        String[] s = br.readLine().split(" ");
        n = Integer.parseInt(s[0]);
        k = Integer.parseInt(s[1]);
        s = br.readLine().split(" ");
        for (int i = 1; i <= n; i++) 
            arr[i] = Long.parseLong(s[i-1]);
        

        // 数据初始化
        for (int i = 0; i <= n; i++) 
            Arrays.fill(f[i], Long.MIN_VALUE);
        

        // 状态初始化 0个数
        f[0][0] = 0;
        for (int i = 1; i <= n; i++) 
            for (int j = 0; j < k; j++) 
                // 状态转移
                f[i][(int) ((j+arr[i])%k)] = Math.max(f[i-1][j]+arr[i], f[i-1][(int) ((j+arr[i])%k)]);
            
        
        // 如果没有合法方案就输出-1
        pw.println(f[n][0] > 0 ? f[n][0] : -1);
        pw.flush();
        br.close();
    

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

大家好,我是snippet,今天是刷蓝桥真题的第二十一天,今天有些事情,还有几个题没看,明天补题 

目录

一、灭鼠先锋

问题描述

运行限制

二、小蓝与钥匙

问题描述

答案提交

运行限制

三、李白打酒加强版

四、机房


一、灭鼠先锋

题目链接:灭鼠先锋 - 蓝桥云课 (lanqiao.cn)

题目内容:

问题描述

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

灭鼠先锋是一个老少咸宜的棋盘小游戏,由两人参与,轮流操作。

灭鼠先锋的棋盘有各种规格,本题中游戏在两行四列的棋盘上进行。游戏的规则为:两人轮流操作,每次可选择在棋盘的一个空位上放置一个棋子,或在同一行的连续两个空位上各放置一个棋子,放下棋子后使棋盘放满的一方输掉游戏。

小蓝和小乔一起玩游戏,小蓝先手,小乔后手。小蓝可以放置棋子的方法很多,通过旋转和翻转可以对应如下四种情况:

XOOO XXOO OXOO OXXO
OOOO OOOO OOOO OOOO

其中 O 表示棋盘上的一个方格为空,X 表示该方格已经放置了棋子。

请问,对于以上四种情况,如果小蓝和小乔都是按照对自己最优的策略来玩游戏,小蓝是否能获胜。如果获胜,请用 V 表示,否则用 L 表示。请将四种情况的胜负结果按顺序连接在一起提交。

运行限制

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

解题思路:

手撸下棋情况

代码:

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

/**
 * @author snippet
 * @data 2023-03-24
 * 灭鼠先锋
 */
public class T1_灭鼠先锋 
    public static void main(String[] args) 
        System.out.println("LLLV");
    

二、小蓝与钥匙

题目链接:小蓝与钥匙 - 蓝桥云课 (lanqiao.cn)

题目内容:

问题描述

小蓝是幼儿园的老师, 他的班上有 28 个孩子, 今天他和孩子们一起进行了 一个游戏。

小蓝所在的学校是寄宿制学校, 28 个孩子分别有一个自己的房间, 每个房 间对应一把钥匙, 每把钥匙只能打开自己的门。现在小蓝让这 28 个孩子分别将 自己宿舍的钥匙上交, 再把这 28 把钥匙随机打乱分给每个孩子一把钥匙, 有 28!=28×27×⋯×128!=28×27×⋯×1 种分配方案。小蓝想知道这些方案中, 有多少种方案恰有 一半的孩子被分到自己房间的钥匙 (即有 14 个孩子分到的是自己房间的钥匙, 有 14 个孩子分到的不是自己房间的钥匙)。

答案提交

这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一 个整数, 在提交答案时只填写这个整数, 填写多余的内容将无法得分。

运行限制

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

解题思路:

代码:

三、李白打酒加强版

题目链接:李白打酒加强版 - 蓝桥云课 (lanqiao.cn)

四、机房

题目链接:机房 - 蓝桥云课 (lanqiao.cn)

以上是关于蓝桥杯31天真题冲刺|题解报告|第二十六天的主要内容,如果未能解决你的问题,请参考以下文章

蓝桥杯备赛刷题

蓝桥杯备赛刷题

蓝桥杯刷题冲刺 | 倒计时9天

2022 第十三届蓝桥杯大赛软件赛省赛(第二场),C/C++ 大学B组题解

蓝桥杯刷题冲刺 | 倒计时16天

蓝桥杯刷题冲刺 | 倒计时8天