2.2 贪心算法

贪心算法的精髓在于,遵循某种规则,不断地选取当前最优解。

硬币问题
假设有 1 元,5元,10元,50元,100元,500元的硬币C1,C5,C10,C50,C500枚,现在需要凑出 A 元
问如何组合才能使硬币的数量最少?

这道题给人的印象就是,为了使得硬币数目最少,尽可能使用面值大的硬币。这种策略就是计算过程中的规则。尽可能使用最大面值,就是当前最优解。

所以,使用每个硬币的数目为:

int t = min(A/Y ,Y_Max); //A为目标,Y为面值,Y_Max为面值为Y的硬币数目。

下面练习一道POJ3617:

2.2.1.BestCowLine

 给定长度为N的字符串S,要构造一个长度为N的字符串T,最开始T是一个空串,随后反复进行如下操作:1.从S的头部删除一个字符,加到T的尾部2.从S的尾部删除一个字符,加到T的头部目标是构建一个字典序尽可能小的字符串T。

这道题的贪心策略就是,每次都选取字符串S两头字典序较小的那个。因为规定只能从两端取,所以若两端的字典序有差别,则可以直接根据当前情况选择当前最优解。我们的需求也是,每次要选择小字典序的字母插入队列。

但是,如果字典序一样该选哪个呢?对于相同的字典序,对于当前情况是没有区别的。可是,如果一个字典序是ZB…CZ,那么如果选择右侧的先,则会导致接下来选择的是ZC…而先选左边,则会产生ZB,这样明显选左边产生的字典序更小。所以,对于相同的两端,我们应该持续比较下一个字符。如果下一个字符也是相同的,则要循环下去。

我其实还思考了蛮久了,为什么要一直循环下去。后来总结道:

|                                    |
|   |                           |   |
|   |   |                   |   |   |
|   |   |   _  .....   |    |   |   |

如果以竖线高低作为字典序高低,只有这种排列的顺序,按照上面循环匹配才有效。
即 “相等项后面字典序递减”
如上图,选取左侧的字典序是 4-3-2-0 ,而选右边则是4-3-2-1,字典序右边高。(让我们忽略省略号,只考虑接下来四个字母)

#include<stdio.h>int n;//length
char str[2001];
//char ans[2000];void create(char* str){int i = 0;int a = n-1;int count = 0;bool left=false;//默认推右边while(i<=a){for(int j=0;i+j<=a-j;j++){//如果字典序相同if(str[i+j]<str[a-j]){left = true;break;}else if(str[i+j]>str[a-j]){left = false;break;}}if(left){putchar(str[i++]);}else{putchar(str[a--]);}}putchar('\n');
}int main(){while(scanf("%d",&n)!=EOF){for(int i=0;i<n;i++){scanf(" %c\n", & str[i]);}str[n]='\0';create(str);}}

2.2.2 Saruman’s Army

poj 3069

在一条直线上,有n个点。从这n个点中选择若干个,给他们加上标记。
对于每一个点,其距离为R以内的区域里必须有一个被标记的点。问至少要有多少点被加上标记。

这道题的贪心策略是,从左到右看这些点。遇到第一个点,以它为圆心画一个半径为R的圆,右侧离圆最近的点作为第一个标记点。为什么不选第一个点作为标记点呢?如果把这个作为萨鲁曼(魔戒梗)的施法范围,第一个人作为标记点,其左侧并没有覆盖任何点。这样就会造成浪费。
第二次,我们就选取上一次标记点的下一个点,作为半径圆心,再按照第一次寻找那样选取点。
直到圆的右侧没有点的时候,程序退出。
这道题感觉还挺简单的,并没有去做它。

2.2.3 Fence Repair

poj 3253

有一个农夫要把一个木板钜成N块给定长度的小木板,每一次费用就是当前锯的这个木板的长度  给定小木板的个数n,各个要求的小木板的长度。求最小费用
如:要5,5,8的木板,需要先将总长度18锯成10,8 再锯成5,5 。最小花费为28.

这道题和搬运水果一样,相当于搬运水果的时空倒流。也就是,我们将两块木板合到一起,花费的代价是这两块木板长度的和。现在要把他们合成一块,需要最少多少的代价。
我们知道,每次合并能减少一块,所以一定需要N-1次合并才能合成一块。但是我们如何选取呢?
根据哈夫曼树,我们应该尽可能使得代价小的木板在叶节点。相当于重复将他们多次合并。处于越深的叶节点,相当于合并这块木板的次数最多。而使得次数多的代价小,能达到最优解。

#include<stdio.h>
#include<queue>
#include<algorithm>
using namespace std;int main(){int n;priority_queue<int,vector<int>,greater<int> > c;int s;while(scanf("%d",&n)!=EOF){long long ans=0;while(!c.empty())c.pop();for(int i=0;i<n;i++){scanf("%d",&s);c.push(s);}int a,b;if(c.size()==1){ans = c.top();break;}while(!c.empty()){a = c.top();c.pop();b = c.top();c.pop();ans += a+b;c.push(a+b);    if(c.size()==1)break;}printf("%lld\n",ans);
}
}

上面的代码使用了优先队列

priority_queue<int >a

这样定义默认是大顶堆结构,即先出队列的是大的值。

priority_queue<int ,vector<int>,greater<int> > a

定义了一个小顶堆队列。
这一数据结构在 #queue 头文件里。

挑战程序设计竞赛笔记-贪心算法相关推荐

  1. 【操作指导 | 代码实现】挑战程序设计竞赛2:算法和数据结构

    书籍封面 第一章 前言 1. 本人衷心建议 ~~~~~~       如果你是一位初学者,我指的是你只会基本的 C/C++ 编程,即使编的很烂,这本书对于你算法和数据结构的提升非常有帮助,所涉及的每一 ...

  2. 《挑战程序设计竞赛》--初级篇习题POJ部分【穷竭搜索+贪心】

    最近看了<挑战程序设计竞赛>初级篇,这里总结一下部分poj上的练习题,主要涉及方面为: 穷竭搜索 and 贪心算法 具体题目: 简单导航 一.穷竭搜索 二.贪心算法 一.穷竭搜索 穷竭搜索 ...

  3. 《挑战程序设计竞赛》阅读笔记二 之 ALDS1_2_C Stable Sort

    <挑战程序设计竞赛>阅读笔记二 之 ALDS1_2_C Stable Sort 第三章 Sort I ALDS1_2_C Stable Sort 这道题目,就是为了说明 冒泡排序是稳定排序 ...

  4. 《挑战程序设计竞赛》推荐及算法相关书籍吐槽

    前几天,秋叶拓哉(iwi).岩田阳一(wata)和北川宜稔(kita_masa)所著,我(watashi).庄俊元(navi)和李津羽(itsuhane)翻译的<挑战程序设计竞赛>,终于通 ...

  5. koch算法c语言递归,【挑战程序设计竞赛】 递归与分治算法

    [挑战程序设计竞赛] 递归与分治算法 [挑战程序设计竞赛] 递归与分治算法 递归与分治算法穷举搜索题目 思路 代码 科赫曲线题目 思路 代码 将问题分解,通过求解局部性的小问题来解决原本的问题,这种技 ...

  6. 《挑战程序设计竞赛(第2版)》习题册攻略

    本项目来源于GitHub 链接: 项目GitHub链接 1 前言 项目为<挑战程序设计竞赛(第2版)>习题册攻略,已完结.可配合书籍或笔记,系统学习算法. 题量:约200道,代码注释内含详 ...

  7. 挑战程序设计竞赛(第2版)》

    <挑战程序设计竞赛(第2版)> 基本信息 作者: (日)秋叶拓哉 岩田阳一 北川宜稔 译者: 巫泽俊 庄俊元 李津羽 丛书名: 图灵程序设计丛书 出版社:人民邮电出版社 ISBN:9787 ...

  8. ICPC程序设计题解书籍系列之三:秋田拓哉:《挑战程序设计竞赛》(第2版)

    白书<挑战程序设计竞赛>(第2版)题目一览 白书:秋田拓哉:<挑战程序设计竞赛>(第2版) 第1章 蓄势待发--准备篇(例题) POJ1852 UVa10714 ZOJ2376 ...

  9. 《挑战程序设计竞赛》 读后感(转载)

    <挑战程序设计竞赛> 读后感 最近要开始准备面试找工作,算法是准备的重中之重,舍友推荐了<挑战程序设计竞赛>这本书.花了一周的时间大体过了一遍,该书真切地让我理解了" ...

最新文章

  1. 数据结构实验之链表二:逆序建立链表
  2. zbb20170824 oracle expdp/impdp 导入导出数据
  3. 不同编程语言在发生stackoverflow之前支持的调用栈最大嵌套层数
  4. 如何遍历一个JS对象中的所有属性,输出键值对--我居然犯错半个小时
  5. ARM中LDR伪指令与LDR加载指令
  6. java 判断 框架类型_第10章-验证框架 --- 验证器类型
  7. linux 简单命令
  8. 二叉查找树--插入、删除、查找
  9. iOS延时执行的几种方法
  10. 像素测量工具_PicPick v5.0.6 屏幕截图工具
  11. ubuntu 16.04 系统安装保留原home分区
  12. Wincc 7.5 SP1使用VBS创建Excel日报表并显示在画面
  13. 机器人自带触觉反馈,隔空微创手术的利器
  14. easy connect显示‘网络请求异常请稍后重试’
  15. 腾讯云直播相关问题处理
  16. 笔记本电脑也是一种微型计算机,计算机一级试题 很权威的哦
  17. DM数据库windwos和linux环境单机安装部署
  18. Vue移动网页开发调试过程(第二篇)——weinre
  19. 《计算机网络技术》第一章测试(题目及答案)
  20. Python打包源码

热门文章

  1. Ubuntu 11.10 Linux 3D桌面完全教程,显卡驱动安装方法,compiz特效介绍,常见问题解答
  2. linux怎样通过手机上网,Linux系统通过手机GPRS上网的设置教程
  3. 腾讯终面:孤单的QQ号码怎么找?
  4. 「人物特写」清华大学教授、IEEE Fellow王志华:几乎所有的AI,到现在为止都是胡扯...
  5. 我国网民规模近10亿:4成初中学历 近3成月收入超5000元
  6. 清华大学计算机系高考生源,清华在京录取圆满结束:生源好、质量优、扩幅大(转贴)...
  7. 【BZOJ3811】玛里苟斯(线性基)
  8. Shell- 获取ESXI主机虚拟交换机中MAC表
  9. 上市 | 章泽天 : 刘强东用10秒钟时间决定投资这个汽车
  10. p4est 2.3.2 安装