洛谷贪心专题讲解 Java语言

简介: 洛谷贪心专题讲解 Java语言

贪心专题讲解

提供一份洛谷网站的贪心题的题单

定义:贪心算法(greedy algorithm [8] ,又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,算法得到的是在某种意义上的局部最优解 。

那么,根据实际刷题经验来看,贪心算法就是根据局部最优解能得到全局最优解。其实通常贪心的难点在于靠自己去根据经验判断,猜测是否可以这样来做。如果自己可以迅速证明自己想的局部贪心策略在全局也会是最优的,那么就可以直接快速做。然而,有的时候自己根据贪心的策略做出来了某个题,但是实际上自己没法用公式或者数学推导证明,也是很有可能的,所以更多的贪心的题通常是根据经验去做。

P1223 排队接水

题目描述

n 个人在一个水龙头前排队接水,假如每个人接水的时间为Ti,请编程找出这n 个人排队的一种顺序,使得n 个人的平均等待时间最小。

输入格式

第一行为一个整数n

第二行n 个整数,第 i 个整数Ti 表示第i 个人的等待时间 Ti

输出格式

输出文件有两行,第一行为一种平均时间最短的排队顺序;第二行为这种排列方案下的平均等待时间(输出结果精确到小数点后两位)。

样例

样例输入

10 
56 12 1 99 1000 234 33 55 99 812

样例输出

3 2 7 8 1 4 9 6 10 5
291.90

提示


image.png

image.png

结论:因此只有当越小的排在越前面的时候,才会使得整体等待时间耗费最少,而平均等待耗费时间跟整体等待耗费时间成正比,因此也就能使得平均等待耗费时间最少。证明完毕。

代码附上:

在这里题还要注意两点:

  • 两位浮点小数输出格式
System.out.printf("%.2f%n",res/n);
  • 用二维数组记录对应的下标,因为题目要求我们输出排队的下标顺序,且是从1开始,因此要记得在数组下标对应的加1
import java.io.*;
import java.util.Arrays;
import java.util.Comparator;
public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        int n = Integer.parseInt(br.readLine().replaceAll(" ", ""));
        String[] s = br.readLine().split(" ");
        int[][] arr = new int[n][2];
        for (int i = 0; i < n; i++) {
            arr[i][0] = Integer.parseInt(s[i]);
            arr[i][1] = i;
        }
        Arrays.sort(arr, (o1, o2) -> {
            if (o1[0] != o2[0]) {
                return o1[0] - o2[0];
            } else {
                return o1[1] - o2[1];
            }
        });
        double res = 0;
        for (int i = 0 ; i < n; i++) {
            System.out.print(arr[i][1] + 1 + " ");
            res += arr[i][0] * (n - i - 1);
        }
        System.out.println();
        System.out.printf("%.2f%n",res/n);
        bw.close();
        br.close();
    }
}

image.png

P1803 线段覆盖

题目背景

题目描述

image.png

输出格式

一个整数最多参加的比赛数目。

样例

样例输入

3
0 2
2 4
1 3

样例输出

2

提示


image.png

import java.io.*;
import java.util.Arrays;
public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        int n = Integer.parseInt(br.readLine().replaceAll(" ", ""));
        int[][] arr = new int[n][2];
        for (int i = 0; i < n; i++) {
           String[] s = br.readLine().trim().split(" ");
           arr[i][0] = Integer.parseInt(s[0]);
           arr[i][1] = Integer.parseInt(s[1]);
        }
        Arrays.sort(arr, (o1, o2) -> {
            return o1[1] - o2[1];
        });
        int res = 0;
        int idx = 0;
        int mi = 0;
        while (idx < n) {
            if (arr[idx][0] >= mi) {
                res++;
                mi = arr[idx][1];
            }
            idx++;
        }
        bw.write(res + "\n");
        bw.flush();
        bw.close();
        br.close();
    }
}

image.png

P1090 [NOIP2004 提高组] 合并果子

题目描述

在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆。多多决定把所有的果子合成一堆。


image.png

样例

样例输入

3 
1 2 9

样例输出

15

提示

image.png

代码如下:

import java.io.*;
import java.util.PriorityQueue;
public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        int n = Integer.parseInt(br.readLine().trim());
        String[] s = br.readLine().trim().split(" ");
        int[] arr = new int[n];
        PriorityQueue<Integer> q = new PriorityQueue<>();
        for (int i = 0 ; i < n ; i++) {
            arr[i] = Integer.parseInt(s[i]);
            q.add(arr[i]);
        }
        int res = 0;
        while (q.size() >= 2) {
            int a = q.poll();
            int b = q.poll();
            res += (a + b);
            q.add(a + b);
        }
        bw.write(res + "\n");
        bw.flush();
        bw.close();
        br.close();
    }
}

p3817 小A的糖果

题目描述

image.png

输出格式

输出一行一个整数,代表最少要吃掉的糖果的数量。

样例

样例输入

3 3
2 2 2

样例输出

1

样例

样例输入

6 1
1 6 1 2 0 4

样例输出

11

样例

样例输入

5 9
3 1 4 1 5

样例输出

0

提示

样例输入输出 1 解释

吃掉第 2 盒中的一个糖果即可。


样例输入输出 2 解释

第 2 盒糖吃掉6 颗,第 4 盒吃掉 2 颗,第 6 盒吃掉 3 颗。


数据规模与约定

image.png

image.png

import java.io.*;
public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        String[] s1 = br.readLine().trim().split(" ");
        int n = Integer.parseInt(s1[0]);
        int x = Integer.parseInt(s1[1]);
        String[] s2 = br.readLine().trim().split(" ");
        int[] arr = new int[n];
        for (int i = 0; i < n; i++) {
            arr[i] = Integer.parseInt(s2[i]);
        }
        long res = 0;
        if (arr[0] > x) {
            res += arr[0] - x;
            arr[0] = x;
        }
        for (int i = 1; i < n; i++) {
            if (arr[i] + arr[i - 1] > x) {
                res += (arr[i] + arr[i - 1] - x);
                arr[i] = x - arr[i - 1];
            }
        }
        bw.write(res + "\n");
        bw.flush();
        bw.close();
        br.close();
    }
}

image.png

总结一下

  1. 贪心算法适用范围有限,仅仅适用于当前策略在局部最优且可以推广至全局最优时,才可以采取贪心策略。
  2. 如果能用贪心算法策略且同时可以用动态规划做的时候,贪心算法在很多时候会能比动态规划的时间复杂度要低或者相等,但是众所周知越是能够最优的往往适用范围就有限。
  3. 有的时候贪心的题自己也没法第一时间证明是否是正确的,可以大胆猜想去做,如果失败了,就可以举特例去反推。当然贪心只是一种策略,还会需要结合一些其他的数据结构或者数据处理才能解题,比如「排序」、「优先队列」。
  4. image.png

相关文章
|
1月前
|
存储 人工智能 算法
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
这篇文章详细介绍了Dijkstra和Floyd算法,这两种算法分别用于解决单源和多源最短路径问题,并且提供了Java语言的实现代码。
65 3
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
|
3月前
|
Java Maven
使用java语言制作一个窗体(弹窗),用来收集用户输入的内容
该博客文章介绍了如何使用Java Swing中的JFrame创建一个窗体来收集用户输入的内容,并提供了详细的实现步骤和完整代码示例。
使用java语言制作一个窗体(弹窗),用来收集用户输入的内容
|
6天前
|
SQL 安全 Java
安全问题已经成为软件开发中不可忽视的重要议题。对于使用Java语言开发的应用程序来说,安全性更是至关重要
在当今网络环境下,Java应用的安全性至关重要。本文深入探讨了Java安全编程的最佳实践,包括代码审查、输入验证、输出编码、访问控制和加密技术等,帮助开发者构建安全可靠的应用。通过掌握相关技术和工具,开发者可以有效防范安全威胁,确保应用的安全性。
18 4
|
4月前
|
Oracle 安全 Java
Java语言简介及发展
Java语言简介及发展
|
5月前
|
数据可视化 Java
Java语言使用DL4J实现图片分类
【6月更文挑战第14天】Java语言使用DL4J实现图片分类
102 3
|
27天前
|
Java 程序员 编译器
在Java编程中,保留字(如class、int、for等)是具有特定语法意义的预定义词汇,被语言本身占用,不能用作变量名、方法名或类名。
在Java编程中,保留字(如class、int、for等)是具有特定语法意义的预定义词汇,被语言本身占用,不能用作变量名、方法名或类名。本文通过示例详细解析了保留字的定义、作用及与自定义标识符的区别,帮助开发者避免因误用保留字而导致的编译错误,确保代码的正确性和可读性。
41 3
|
30天前
|
移动开发 Java 大数据
深入探索Java语言的核心优势与现代应用实践
【10月更文挑战第10天】深入探索Java语言的核心优势与现代应用实践
46 4
|
1月前
|
存储 Java 数据安全/隐私保护
Java中的域,什么是域?计算机语言中的域是什么?(有代码实例)
文章解释了Java中域的概念,包括实例域、静态域、常量域和局部域,以及它们的特点和使用场景。
48 2
|
1月前
|
Java 数据安全/隐私保护 C++
Java语言关键字
Java语言关键字
20 2
|
1月前
|
分布式计算 安全 Java
Java语言的特点?
Java语言的特点?