| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 数据结构与算法 -> 洛谷贪心专题讲解 Java语言 -> 正文阅读 |
|
[数据结构与算法]洛谷贪心专题讲解 Java语言 |
贪心专题讲解提供一份洛谷网站的贪心题的题单 定义:贪心算法(greedy algorithm [8] ,又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,算法得到的是在某种意义上的局部最优解 。 那么,根据实际刷题经验来看,贪心算法就是根据局部最优解能得到全局最优解。其实通常贪心的难点在于靠自己去根据经验判断,猜测是否可以这样来做。如果自己可以迅速证明自己想的局部贪心策略在全局也会是最优的,那么就可以直接快速做。然而,有的时候自己根据贪心的策略做出来了某个题,但是实际上自己没法用公式或者数学推导证明,也是很有可能的,所以更多的贪心的题通常是根据经验去做。 P1223 排队接水题目描述有 n n n 个人在一个水龙头前排队接水,假如每个人接水的时间为 T i T_i Ti?,请编程找出这 n n n 个人排队的一种顺序,使得 n n n 个人的平均等待时间最小。 输入格式第一行为一个整数 n n n。 第二行 n n n 个整数,第 i i i 个整数 T i T_i Ti? 表示第 i i i 个人的等待时间 T i T_i Ti?。 输出格式输出文件有两行,第一行为一种平均时间最短的排队顺序;第二行为这种排列方案下的平均等待时间(输出结果精确到小数点后两位)。 样例 #1样例输入 #1
样例输出 #1
提示n ≤ 1000 , t i ≤ 1 0 6 n \leq 1000,t_i \leq 10^6 n≤1000,ti?≤106,不保证 t i t_i ti? 不重复。 当 t i t_i ti? 重复时,按照输入顺序即可(sort 是可以的) 解题思路
该题贪心策略的证明: 我们假定第 i i i个人的取水时间为 t i t_i ti?,那么如果存在排队的某个下标顺序为 [ 0... i , j , k . . . n ] [0...i,j,k...n] [0...i,j,k...n],使得总的等待的时间 t t t。我们可以取任意区间内,比如我们这里取 [ i , j , k ] [i,j,k] [i,j,k],对应的时间为 [ t i , t j , t k ] [t_i,t_j,t_k] [ti?,tj?,tk?],其中不满足 t i ≤ t j ≤ t k t_i \leq t_j \leq t_k ti?≤tj?≤tk?,那么该区间内所耗费的等待时间总长 t s u m = t i ? 2 + t j ? 1 t_{sum} = t_i * 2 + t_j * 1 tsum?=ti??2+tj??1,可以看到 t s u m t_{sum} tsum?和 t i , t j , t k t_i,t_j,t_k ti?,tj?,tk?均成正线性关系,且 t i t_i ti?的系数最大,那么此时当前仅当 t i ≤ t j ≤ t k t_i \leq t_j \leq t_k ti?≤tj?≤tk?,才能使得 t s u m t_{sum} tsum?是最小的。 结论:因此只有当越小的排在越前面的时候,才会使得整体等待时间耗费最少,而平均等待耗费时间跟整体等待耗费时间成正比,因此也就能使得平均等待耗费时间最少。证明完毕。 代码附上: 在这里题还要注意两点:
时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn),空间复杂度 O ( l o g n ) O(logn) O(logn)。 P1803 线段覆盖题目背景题目描述现在各大 oj 上有 n n n 个比赛,每个比赛的开始、结束的时间点是知道的。 yyy 认为,参加越多的比赛,noip 就能考的越好(假的)。 所以,他想知道他最多能参加几个比赛。 由于 yyy 是蒟蒻,如果要参加一个比赛必须善始善终,而且不能同时参加 2 2 2 个及以上的比赛。 输入格式第一行是一个整数 n n n ,接下来 n n n 行每行是 2 2 2 个整数 a i , b i a_{i},b_{i} ai?,bi? ( a i < b i a_{i}<b_{i} ai?<bi? ),表示比赛开始、结束的时间。 输出格式一个整数最多参加的比赛数目。 样例 #1样例输入 #1
样例输出 #1
提示对于 20 % 20\% 20% 的数据, n ≤ 10 n \le 10 n≤10。 对于 50 % 50\% 50% 的数据, n ≤ 1 0 3 n \le 10^3 n≤103。 对于 70 % 70\% 70% 的数据, n ≤ 1 0 5 n \le 10^{5} n≤105。 对于 100 % 100\% 100% 的数据, 1 ≤ n ≤ 1 0 6 1\le n \le 10^{6} 1≤n≤106 , 0 ≤ a i < b i ≤ 1 0 6 0 \le a_{i} < b_{i} \le 10^6 0≤ai?<bi?≤106。 解题思路:这个题相当于求的是不含重复区间的最多区间数量。
证明:假定存在如下的比赛排列, [ a 0 , b 0 ] , [ a 1 , b 1 ] , [ a 2 , b 2 ] , . . . [ a i , b i ] , . . . , [ a j , b j ] , [ a n ? 1 , . . . , b n ? 1 ] [a_{0},b_{0}],[a_{1},b_{1}],[a_{2},b_{2}],...[a_{i},b_{i}],...,[a_{j},b_{j}],[a_{n-1},...,b_{n-1}] [a0?,b0?],[a1?,b1?],[a2?,b2?],...[ai?,bi?],...,[aj?,bj?],[an?1?,...,bn?1?],其中 a i , b i a_i,b_i ai?,bi?分别代表一个比赛的开始时间和结束时间。且都是按照结束时间 b k b_k bk?升序排列的。那么对于任意区间 [ a i , b i ] [a_i,b_i] [ai?,bi?]而言,要想计算当前时间段已经能够参与的最多的比赛,就是看 a i a_i ai?时间段之前,在 l < p l < p l<p,一共有多少个可以连续的 b l , b p b_l,b_p bl?,bp?可以满足 b l ≤ a p b_l \leq a_p bl?≤ap?.
时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn),空间复杂度 O ( l o g n ) O(logn) O(logn)。 P1090 [NOIP2004 提高组] 合并果子题目描述在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆。多多决定把所有的果子合成一堆。 每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和。可以看出,所有的果子经过 n ? 1 n-1 n?1 次合并之后, 就只剩下一堆了。多多在合并果子时总共消耗的体力等于每次合并所耗体力之和。 因为还要花大力气把这些果子搬回家,所以多多在合并果子时要尽可能地节省体力。假定每个果子重量都为 1 1 1 ,并且已知果子的种类 数和每种果子的数目,你的任务是设计出合并的次序方案,使多多耗费的体力最少,并输出这个最小的体力耗费值。 例如有 3 3 3 种果子,数目依次为 1 1 1 , 2 2 2 , 9 9 9 。可以先将 1 1 1 、 2 2 2 堆合并,新堆数目为 3 3 3 ,耗费体力为 3 3 3 。接着,将新堆与原先的第三堆合并,又得到新的堆,数目为 12 12 12 ,耗费体力为 12 12 12 。所以多多总共耗费体力 = 3 + 12 = 15 =3+12=15 =3+12=15 。可以证明 15 15 15 为最小的体力耗费值。 输入格式共两行。 第二行包含 n n n 个整数,用空格分隔,第 i i i 个整数 a i ( 1 ≤ a i ≤ 20000 ) a_i(1\leq a_i\leq 20000) ai?(1≤ai?≤20000) 是第 i i i 种果子的数目。 输出格式一个整数,也就是最小的体力耗费值。输入数据保证这个值小于 2 31 2^{31} 231 。 样例样例输入
样例输出
提示对于 30 % 30\% 30% 的数据,保证有 n ≤ 1000 n \le 1000 n≤1000: 对于 50 % 50\% 50% 的数据,保证有 n ≤ 5000 n \le 5000 n≤5000; 对于全部的数据,保证有 n ≤ 10000 n \le 10000 n≤10000。 解题思路:
证明: 假设存在 [ a o , a 1 , . . . a i , . . . , a j , . . . , a k , a n ? 1 ] [a_o,a_1,...a_i, ...,a_j,...,a_k,a_n-1] [ao?,a1?,...ai?,...,aj?,...,ak?,an??1]的体力值,任意取出四个数 a i , a j , a k , a p a_i,a_j,a_k,a_p ai?,aj?,ak?,ap?,那么假设这四个数当中最小的两个数是 a i , a j a_i,a_j ai?,aj?,就一定会满足 a i + a j ≤ a k + a p a_i + a_j \leq a_k + a_p ai?+aj?≤ak?+ap?,合并的耗费的体力值 a i + a j a_i + a_j ai?+aj?也一定是最小的,然后再与任意新的体力值 a m a_m am?合并,一定会满足 a i + a j + a m ≤ a k + a p + a m a_i + a_j + a_m \leq a_k + a_p + a_m ai?+aj?+am?≤ak?+ap?+am?.因此要想得到总体的最小的体力耗费值,当且仅当每次合并两个的体力值是最小的。 代码如下:
p3817 小A的糖果题目描述小 A 有 n n n 个糖果盒,第 i i i 个盒中有 a i a_i ai? 颗糖果。 小 A 每次可以从其中一盒糖果中吃掉一颗,他想知道,要让任意两个相邻的盒子中糖的个数之和都不大于 x x x,至少得吃掉几颗糖。 输入格式输入的第一行是两个用空格隔开的整数,代表糖果盒的个数 n n n 和给定的参数 x x x。 第二行有 n n n 个用空格隔开的整数,第 i i i 个整数代表第 i i i 盒糖的糖果个数 a i a_i ai?。 输出格式输出一行一个整数,代表最少要吃掉的糖果的数量。 样例 #1样例输入 #1
样例输出 #1
样例 #2样例输入 #2
样例输出 #2
样例 #3样例输入 #3
样例输出 #3
提示样例输入输出 1 解释吃掉第 2 盒中的一个糖果即可。 样例输入输出 2 解释第 2 盒糖吃掉 6 6 6 颗,第 4 盒吃掉 2 2 2 颗,第 6 盒吃掉 3 3 3 颗。 数据规模与约定
解题思路: 这个题一开始我想的是既然想得到的是「任意两个相邻的盒子中」糖的数量之和不大于 x x x,那么我就直接排序,从最大值一路减过来。如果最大的两个盒子里的糖果数量加起来都不大于 x x x了,那么所有的盒子里的糖果肯定会满足条件。 但是,忽略了一点,是相邻的。如果初始给定的顺序比如 i , j , k {i,j,k} i,j,k,, a [ i ] + a [ j ] ≤ x a[i] + a[j] \leq x a[i]+a[j]≤x且 a [ j ] + a [ k ] ≤ x a[j] + a[k] \leq x a[j]+a[k]≤x,那么实际上就不需要额外吃糖果了,但是根据我的第一想法可能会出现排序后是 j , i , k j,i,k j,i,k,会有 a [ i ] + a [ k ] > x a[i] + a[k] > x a[i]+a[k]>x,那么肯定会需要吃掉 a [ i ] + a [ k ] ? x a[i] + a[k] - x a[i]+a[k]?x颗糖果才行。因此我的第一贪心想法是不对的。这就是一个明显的反例。所以可以看出来,有时候自己想的贪心不一定是正确的贪心策略,如果不是正确的贪心策略的,通常是会出错的。 正确的解题做法:
证明: 对于 i ? 1 i \geqslant 1 i?1而言,如果当前值和前一项的和比 x x x大的话,那么当前值和前一项的值就可以一起减去 a [ i ? 1 ] a[i-1] a[i?1]颗糖果,这样子就可以让任意相邻的两个数的和 a [ i ] + a [ i ? 1 ] ≤ x a[i] + a[i - 1] \leq x a[i]+a[i?1]≤x且减去的值恰好为两个只超过 x x x的部分,而不需要额外多减去。 附上代码:
时间复杂度 O ( n ) O(n) O(n),空间复杂度 O ( 1 ) O(1) O(1) 总结一下
|
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 | -2024/12/30 1:11:22- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |