贪心算法
来源:互联网 发布:mysql 查看用户连接数 编辑:程序博客网 时间:2024/06/06 15:59
贪心算法
贪心算法是指在对问题求解时,总是作出在当前看来是最好的选择。也就是说,不从整体上加以考虑,它所作出的仅仅是在某种意义上的局部最优解(是否是全局最优,需要证明)。
如果我们要用贪心算法求解某问题的整体最优解,必须首先证明贪心思想在该问题的应用结果就是最优解!!
如果我们要用贪心算法求解某问题的整体最优解,必须首先证明贪心思想在该问题的应用结果就是最优解!!
贪心算法的基本步骤:
1、从问题的某个初始解出发。
2、采用循环语句,当可以向求解目标前进一步时,就根据局部最优策略,得到一个部分解,缩小问题的范围或规模。
3、将所有部分解综合起来,得到问题的最终解。
2、采用循环语句,当可以向求解目标前进一步时,就根据局部最优策略,得到一个部分解,缩小问题的范围或规模。
3、将所有部分解综合起来,得到问题的最终解。
一、事件序列问题
已知n个事件的发生时刻和结束时刻(见下表,表中事件已按结束时刻升序排序)。一些在时间上没有重叠的事件,可以构成一个事件序列,如事件{2,8,10}。事件序列包含的事件数目,称为该事件序列的长度。请编程找出一个最长的事件序列。
【算法分析】
不妨用begin[i]和end[i]表示事件i的开始时刻和结束时刻。则原题的要求就是找一个最长的序列a1 < a2 < … < an,满足:
begin[a1] < end[a1] <= … <= begin[an]< end[an]
可以证明,如果在可能的事件a1 < a2 < … < an中选取在时间上不重叠的最长序列,那么一定存在一个包含a1(结束最早)的最长序列。(证明略)
【算法分析】
不妨用begin[i]和end[i]表示事件i的开始时刻和结束时刻。则原题的要求就是找一个最长的序列a1 < a2 < … < an,满足:
begin[a1] < end[a1] <= … <= begin[an]< end[an]
可以证明,如果在可能的事件a1 < a2 < … < an中选取在时间上不重叠的最长序列,那么一定存在一个包含a1(结束最早)的最长序列。(证明略)
【程序1】今年暑假不AC
【问题描述】
“今年暑假不AC?”
“是的。”
“那你干什么呢?”
“看世界杯呀,笨蛋!”
“@#$%^&*%...”
确实如此,世界杯来了,球迷的节日也来了,估计很多OIer也会抛开电脑,奔向电视了。
作为球迷,一定想看尽量多的完整的比赛,当然,作为新时代的好青年,你一定还会看一些其它的节目,比如新闻联播(永远不要忘记关心国家大事)、非常6+7、超级女生,以及韩国热播的《running man》等等,假设你已经知道了所有你喜欢看的电视节目的转播时间表,你会合理安排吗?(目标是能看尽量多的完整节目)
【输入】
第一行只有一个整数n(n<=100),表示你喜欢看的节目的总数,然后是n行数据,每行包括两个数据Ti_s,Ti_e (0<=i<=n),分别表示第i个节目的开始和结束时间,为了简化问题,每个时间都用一个正整数表示。
【输出】
输出能完整看到的电视节目的个数。
【样例输入】
12
1 3
3 4
0 7
3 8
15 19
15 20
10 15
8 18
6 12
5 10
4 14
2 9
【样例输出】
5
【分析】按照每个节目的结束时间排序,目的是使剩余时间留下,再判断还能看几个节目。对节目时间的排序结束后,依次判断:这次要看的节目的开始时间是否大于上次看的节目的结束时间,若是大于等于,则这个节目可以完整观看;若是小于则不能完整观看,跳到下一个节目继续判断。
对于样例数据,对结束时间进行排序后的数组如下:
“今年暑假不AC?”
“是的。”
“那你干什么呢?”
“看世界杯呀,笨蛋!”
“@#$%^&*%...”
确实如此,世界杯来了,球迷的节日也来了,估计很多OIer也会抛开电脑,奔向电视了。
作为球迷,一定想看尽量多的完整的比赛,当然,作为新时代的好青年,你一定还会看一些其它的节目,比如新闻联播(永远不要忘记关心国家大事)、非常6+7、超级女生,以及韩国热播的《running man》等等,假设你已经知道了所有你喜欢看的电视节目的转播时间表,你会合理安排吗?(目标是能看尽量多的完整节目)
【输入】
第一行只有一个整数n(n<=100),表示你喜欢看的节目的总数,然后是n行数据,每行包括两个数据Ti_s,Ti_e (0<=i<=n),分别表示第i个节目的开始和结束时间,为了简化问题,每个时间都用一个正整数表示。
【输出】
输出能完整看到的电视节目的个数。
【样例输入】
12
1 3
3 4
0 7
3 8
15 19
15 20
10 15
8 18
6 12
5 10
4 14
2 9
【样例输出】
5
【分析】按照每个节目的结束时间排序,目的是使剩余时间留下,再判断还能看几个节目。对节目时间的排序结束后,依次判断:这次要看的节目的开始时间是否大于上次看的节目的结束时间,若是大于等于,则这个节目可以完整观看;若是小于则不能完整观看,跳到下一个节目继续判断。
对于样例数据,对结束时间进行排序后的数组如下:
1 3 0 3 2 5 6 4 10 8 15 15 3 4 7 8 9 10 12 14 15 18 19 20然后进行依次判断发现有5个节目时可以完整观看的,即上面的5组红色字体,接着便输出结果。
【C++】#include<iostream>#include<algorithm>#include<cstring>using namespace std;int n;struct show{ int begin; int end;}a[110];bool cmp(show a,show b){ return a.end<b.end;}int main(){cin >> n;int ans=1,i;memset(a,0,sizeof(a));for(i=0;i<n;i++) cin >> a[i].begin >> a[i].end;sort(a,a+n,cmp);int tmp=a[0].end;for(i=1;i<n;i++)if(a[i].begin>=tmp){ans++;tmp=a[i].end;}cout << ans << endl;return 0;}
二、部分背包问题
给定n种物品和一个背包。物品i的重量是Wi,其价值为Vi,背包的容量为C。应如何选择装入背包的物品,使得装入背包中物品的总价值最大,可以选择物品i的一部分,而不一定要全部装入背包,1≤i≤n。
用贪心算法解背包问题的基本步骤:
首先计算每种物品单位重量的价值Vi/Wi,然后,依贪心选择策略,将尽可能多的单位重量价值最高的物品装入背包。若将这种物品全部装入背包后,背包内的物品总重量未超过C,则选择单位重量价值次高的物品并尽可能多地装入背包。依此策略一直地进行下去,直到背包装满为止。
用贪心算法解背包问题的基本步骤:
首先计算每种物品单位重量的价值Vi/Wi,然后,依贪心选择策略,将尽可能多的单位重量价值最高的物品装入背包。若将这种物品全部装入背包后,背包内的物品总重量未超过C,则选择单位重量价值次高的物品并尽可能多地装入背包。依此策略一直地进行下去,直到背包装满为止。
部分背包的算法框架如下:按单位重量价值v[i]/w[i]降序排列w[i]和v[i];将数组a[n]初始化为0;i=1;while (w[i]<=C){ 将第i个物品放入背包:a[i]=1; C=C-w[i]; i++}a[i]=C/w[i];程序代码片段:Sort(n,v,w);int i;for (i=1;i<=n;i++) a[i]=0;float c=M;for (i=1;i<=n;i++) {if (w[i]>c) break;a[i]=1; c=c-w[i];}if (i<=n) a[i]=c/w[i];
三、区间覆盖问题
用i来表示x轴上坐标为[i-1,i]的区间(长度为1),并给出m(1<=M<=200)个不同的整数,表示m个这样的区间。现在让你画几条线段覆盖住所有的区间,条件是:每条线段可以任意长,但是要求所画线段之和最小,并且线段的数目不超过n(1<=N<=50)。
例如:m=5个整数1、3、4、8和11表示区间,要求所用线段不超过n=3条
【分析】如果n>=m,那么显然用m条长度为1的线段可以覆盖住所有的区间,所求的线段总长为m。
如果n=1,那么显然所需线段总长为:…
如果n=2,相当于n=1的情况下从某处断开(从哪儿断开呢?)。
如果n=k呢?
例如:m=5个整数1、3、4、8和11表示区间,要求所用线段不超过n=3条
【分析】如果n>=m,那么显然用m条长度为1的线段可以覆盖住所有的区间,所求的线段总长为m。
如果n=1,那么显然所需线段总长为:…
如果n=2,相当于n=1的情况下从某处断开(从哪儿断开呢?)。
如果n=k呢?
【程序2】移动桌子 (laoj1333)
著名的ACM(先进的电脑制造商)公司租了一个楼层,形状如下图。
这层楼中间有个走廊,走廊的南面和北面各有200各房间。最近公司制定了一个计划,对这层楼进行改造。改造包括从一些房间中移动一些桌子到另外一些房间。因为楼道很窄,桌子很大,每次只有一张桌子可以通过走廊。为了不浪费时间,移动桌子的这个计划需要高效处理。经理想出了以下做法:搬动一张桌子从一个房间到另一个房间可以在10分钟内完成。当从一个房间i移动一张桌子到房间j时,房间i到房间j的这部分走廊就被占用。所以,在每10分钟时间内,同时移动的几张桌子不能共享它们所经过的走廊。经理明确说明了同时移动的可能情况和不可能情况。
对于每一个房间,只有一张桌子可以移入或移出。现在,经理寻求以最少的时间去移动所有的桌子。你的任务是写一个程序来解决经理的问题。
输入
第一行包含一个整数n,1≤n≤200,表示要把桌子的数量。以下n行包含两个正整数s和t,代表一张桌子是从房间s搬到房号t(每个房间号码最多出现一次)。
输出
输出完成移动的最小分钟数。
样例输入
3
4
10 20
30 40
50 60
70 80
2
1 3
2 200
3
10 100
20 80
30 50
样例输出
10
20
30
【分析】
1、如果没有交叉,总时间应该是多少?
2、影响搬运时间的因素是什么?
3、如果每趟处理都包含最大重叠,处理后的效果是什么?
4、得出什么结论?
其实,贪心策略是这样的:
对门其实考虑成一个点,故只要200个就可,然后统计经过每个点的次数,次数最大即为需要的最短时间。
这层楼中间有个走廊,走廊的南面和北面各有200各房间。最近公司制定了一个计划,对这层楼进行改造。改造包括从一些房间中移动一些桌子到另外一些房间。因为楼道很窄,桌子很大,每次只有一张桌子可以通过走廊。为了不浪费时间,移动桌子的这个计划需要高效处理。经理想出了以下做法:搬动一张桌子从一个房间到另一个房间可以在10分钟内完成。当从一个房间i移动一张桌子到房间j时,房间i到房间j的这部分走廊就被占用。所以,在每10分钟时间内,同时移动的几张桌子不能共享它们所经过的走廊。经理明确说明了同时移动的可能情况和不可能情况。
对于每一个房间,只有一张桌子可以移入或移出。现在,经理寻求以最少的时间去移动所有的桌子。你的任务是写一个程序来解决经理的问题。
输入
第一行包含一个整数n,1≤n≤200,表示要把桌子的数量。以下n行包含两个正整数s和t,代表一张桌子是从房间s搬到房号t(每个房间号码最多出现一次)。
输出
输出完成移动的最小分钟数。
样例输入
3
4
10 20
30 40
50 60
70 80
2
1 3
2 200
3
10 100
20 80
30 50
样例输出
10
20
30
【分析】
1、如果没有交叉,总时间应该是多少?
2、影响搬运时间的因素是什么?
3、如果每趟处理都包含最大重叠,处理后的效果是什么?
4、得出什么结论?
其实,贪心策略是这样的:
对门其实考虑成一个点,故只要200个就可,然后统计经过每个点的次数,次数最大即为需要的最短时间。
C++语言描述如下:#include<iostream>#include<cstring>using namespace std;int main(){int i,j,n,a[201];int s,d,t,k,ans=-1; memset(a,0,sizeof(a)); cin >> n; for(j=0;j> s >> d; s=(s-1)/2; d=(d-1)/2; if(s>d){t=s;s=d;d=t;} for(k=s;k<=d;k++) a[k]++; } for(j=0;j<200;j++) if(a[j]>ans) ans=a[j]; cout << ans*10 << endl; return 0; }
四、单源最短路径
其基本思想是,设置顶点集合S并不断地作贪心选择来扩充这个集合。一个顶点属于集合S当且仅当从源到该顶点的最短路径长度已知。
初始时,S中仅含有源。设u是G的某一个顶点,把从源到u且中间只经过S中顶点的路称为从源到u的特殊路径,并用数组dist记录当前每个顶点所对应的最短特殊路径长度。Dijkstra算法每次从V-S中取出具有最短特殊路长度的顶点u,将u添加到S中,同时对数组dist作必要的修改。一旦S包含了所有V中顶点,dist就记录了从源到所有其它顶点之间的最短路径长度。
初始时,S中仅含有源。设u是G的某一个顶点,把从源到u且中间只经过S中顶点的路称为从源到u的特殊路径,并用数组dist记录当前每个顶点所对应的最短特殊路径长度。Dijkstra算法每次从V-S中取出具有最短特殊路长度的顶点u,将u添加到S中,同时对数组dist作必要的修改。一旦S包含了所有V中顶点,dist就记录了从源到所有其它顶点之间的最短路径长度。
0 1
- 【贪心】贪心算法总结
- 贪心算法
- 贪心算法
- 贪心算法
- 贪心算法
- 贪心算法
- 贪心算法
- 贪心算法
- 贪心算法
- 贪心算法
- 贪心算法
- 贪心算法
- 贪心算法
- 贪心算法
- 贪心算法
- 贪心算法
- 贪心算法
- 贪心算法
- 关于listview上下滑动imageview图片混乱问题
- 单例设计模式
- 个人静态blog
- shell中的命令替换
- 异常处理——异常处理简介之UnhandledExceptionFilter(1)
- 贪心算法
- 通过反射访问构造方法(学习笔记)
- Laravel5遇到的问题以及解决方案 -- PDOException SQLSTATE[HY000] [2002] No such file or directory
- Spring MVC集成Tiles3
- 宽度优先搜索
- jstl自定义函数的使用
- 基于QT的TCP协议实现的通信小程序
- bootstrap-table插件实现ajax服务端分页显示
- BZOJ2229: [Zjoi2011]最小割 分治最小割