第十四届蓝桥杯冲刺打卡31天day26

1、玩具

排序后以距离2进行遍历,只加更贵的。

链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
 

题目描述

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

输入描述:

第一行一个正整数 n(1≤n≤106)。

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

输出描述:

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

示例1

输入

3
1 2 3

输出

4

说明

第二个和第三个一起买,花 3 元,再花 1 元买下第一个,合计 4 元。
import java.util.Scanner;
import java.util.Arrays;
public class Main{
    static long values = 0L;
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
            int n = sc.nextInt();
            int []value = new int[n];
            for(int i=0;i<n;i++){
                value[i]=sc.nextInt();
            }
        Arrays.sort(value);//排序
        for(int i=n-1;i>=0;i-=2){//因为是购买2个从中舍去比较小的,那么我们只需要排序后将从大到小每次占据首位的加上即可
            values+=value[i];
        }
        System.out.println(values);
        }
    }

2、滑雪

dp+dfs

思路看注释

描述

给定一个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  
import java.util.*;
import java.io.*;
//动态规划+dfs
public class Main {
    static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    static PrintWriter out = new PrintWriter(new BufferedWriter(
                new OutputStreamWriter(System.out)));
    static int[]dx = new int[] {0, 1, -1, 0}; //定义状态
    static int[]dy = new int[] {1, 0, 0, -1};
    static int n = 0;
    static int m = 0;
    public static void main(String[] args) throws IOException {
        String[]s = in.readLine().split(" ");
        //定义滑雪场矩阵行列
        n = Integer.parseInt(s[0]);
        m = Integer.parseInt(s[1]);
        int[][] map = new int[n][m];
        //给滑雪场赋值
        for (int i = 0; i < n; i++) {
            s = in.readLine().split(" ");
            for (int j = 0; j < m; j++) {
                map[i][j] = Integer.parseInt(s[j]);
            }
        }
        //通过遍历滑雪场上的各元素值来得到答案
        System.out.println(answer(map));
        in.close();
        out.flush();
    }

    private static int answer(int[][] map) {
        int[][] dp = new int[n][m];//生成动态规划数组
//        for(int i=0;i<m;i++) Arrays.fill(dp[i],1);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                //通过dfs每一个点来获得符合要求的最远路径长度
                dfs(i, j, map, dp);
            }
        }
        int res = 0;//计算每一个点满足条件的最大长度,注意每次需要更新
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                //比较每一个点动态规划后的长度和此前最长的长度哪个更长,保留更长值
                res = Math.max(res, dp[i][j]); //保留有最长路径的那个点的值
            }
        }
        return res;//返回结果
    }

    private static int  dfs( int i, int j, int[][] map, int[][] dp) {
        if (i < 0 || j < 0 || i >= n ||
                j >= m) { //需要判断是否超过边界,初始点是从0,0开始的
            return 0;
        }
        if (dp[i][j] !=
                0) { //如果此点已经得到了其最远路径值那就没有必要再进行dfs了,直接返回其长度即可,这样计算会更加方便,比如25到了21,21往下的数据已经计算过了,就可以直接加上,就不需要再进行遍历
            return dp[i][j];
        }
        int max = 1;//滑道本身也是一个距离,所以要从1开始计算
        for (int d = 0; d < 4; d++) {
            int newx = i + dx[d]; //dfs过程
            int newy = j + dy[d]; //dfs过程
            if (newx >= 0 && newx < n && newy >= 0 && newy < m &&
                    map[newx][newy] <
                    map[i][j]) {//判断边界及高度应是递减,如果往四个方向走都没有满足条件的,那么当前点的滑道自然就是其本身,这就是为什么每次需要重新赋值1的原因
                max = Math.max(max, dfs(newx, newy, map,
                                        dp) + 1); //判断当前点能够到达的最远距离,例如25->24->23->22->21......,每次通过dfs进行判断下一个点(newx,newy)是否能够往下走,这个过程就可以将每次传送过来的点所能够到达的最远距离存储在dp[i][j]里
            }//max每次都是在第一个初始点的基础上累加的,如果当前点它可以一直满足条件往下走,那么通过dfs(newx,newy,map,dp)+1这条语句便可以做到累加

        }
        //给每一个点赋值动态规划后所获得的满足条件的最大路径长度
        dp[i][j] = max;
        return max;//将当前点的最大路径长度返回
    }
}

 3、abb

存储每个字符出现的次数,再按顺序进行匹配,因为abb格式,所以要注意遍历的终点边界,且由于是abb型,后边的字符如果不能出现2+次数,那么也不可能匹配成功,注意规律:

例如 ,b 生成 bcc,bcc,bcc,bcc ,此处的b分别是1下标的b与3下标的b,c分别是下标2,4,5的c

即第一个b后三个c,3*2/2=3,第二个b后两个c,2*1/2=1,3+1=4,详细见注释

描述

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

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

  1. 字符串长度为 3 。
  2. 字符串后两位相同。
  3. 字符串前两位不同。

输入描述:

第一行一个正整数 n

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

1≤n≤105

输出描述:

"abb" 型的子序列个数。

示例1

输入:

6
abcbcc

输出:

8

说明:

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

示例2

输入:

4
abbb

输出:

3
import java.util.*;
public class Main {
    static long sum = 0L;
    public static void main(String[]args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        String s = sc.next();
        int[]word = new int[26]; //26字母数组
        for (int i = 0; i < n; i++) {
            word[s.charAt(i) - 'a']++; //每个字母出现的次数
        }
        for (int i = 0; i < n - 2;i++) { //因为是计算abb型序列有多少,那么长度不能少于3,所以遍历到倒数第三个字符即可
            int wordi = s.charAt(i) - 'a'; //得到当前字符对应的下标
            word[wordi]--;//针对每个字符判断其后边的字符有哪些是可以达到2个以上的,当然不包括它本身,因为遍历往后走,所以当前字符判断以后要减1
            for (int j = 0; j < 26;
                    j++) { //将当前字符与所有字符进行匹配,只有出现2次及以上的才可以匹配,不包括它本身
                if (word[j] >= 2 && j != wordi) {
                    sum += word[j] * (word[j] - 1)/2; //例如 b 生成 bcc,bcc,bcc,bcc ,此处的b分别是1下标的b与3下标的b,c分别是下标2,4,5的c
                    //即第一个b后三个c,3*2/2=3,第二个b后两个c,2*1/2=1,3+1=4
                }
            }
        }
        System.out.println(sum);
    }
}

4、小红取数

描述

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

输入描述:

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

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

1≤n,k≤103

1≤ai​≤1010

输出描述:

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

示例1

输入:

5 5
4 8 2 9 1

输出:

20

说明:

取后四个数即可

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值