贪心的定义:
贪心选择是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。这是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别。贪心选择是采用从顶向下、以迭代的方法做出相继选择,每做一次贪心选择就将所求问题简化为一个规模更小的子问题。对于一个具体问题,要确定它是否具有贪心选择的性质,我们必须证明每一步所作的贪心选择最终能得到问题的最优解。
最优子结构:
当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。运用贪心策略在每一次转化时都取得了最优解。问题的最优子结构性质是该问题可用贪心算法或动态规划算法求解的关键特征。贪心算法的每一次操作都对结果产生直接影响,而动态规划则不是。贪心算法对每个子问题的解决方案都做出选择,不能回退;动态规划则会根据以前的选择结果对当前进行选择,有回退功能。动态规划主要运用于二维或三维问题,而贪心一般是一维问题 。
例题:
确实如此,世界杯来了,球迷的节日也来了,估计很多ACMer也会抛开电脑,奔向电视了。
作为球迷,一定想看尽量多的完整的比赛,当然,作为新时代的好青年,你一定还会看一些其它的节目,比如新闻联播(永远不要忘记关心国家大事)、非常6+7、超级女生,以及王小丫的《开心辞典》等等,假设你已经知道了所有你喜欢看的电视节目的转播时间表,你会合理安排吗?(目标是能看尽量多的完整节目)
作为球迷,一定想看尽量多的完整的比赛,当然,作为新时代的好青年,你一定还会看一些其它的节目,比如新闻联播(永远不要忘记关心国家大事)、非常6+7、超级女生,以及王小丫的《开心辞典》等等,假设你已经知道了所有你喜欢看的电视节目的转播时间表,你会合理安排吗?(目标是能看尽量多的完整节目)
Input
输入数据包含多个测试实例,每个测试实例的第一行只有一个整数n(n<=100),表示你喜欢看的节目的总数,然后是n行数据,每行包括两个数据Ti_s,Ti_e (1<=i<=n),分别表示第i个节目的开始和结束时间,为了简化问题,每个时间都用一个正整数表示。n=0表示输入结束,不做处理。
Output
对于每个测试实例,输出能完整看到的电视节目的个数,每个测试实例的输出占一行。
Sample Input
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
0
Sample Output
5
解析:
要看尽可能多的电视节目,首先需要尽可能的每时每刻都在看,而且还要考虑不能看那种时间特别长的节目,这会让我们因为一个节目而浪费许多时间,首先可以把节目的开始和结束时间存到一个结构体数组中,然后对结构体数组根据结束时间进行排序,然后从第一个节目开始看,如果下一个节目的开始时间早于上一个的结束时间,这个节目就不能看了,然后继续看下一个节目,如果下一个节目的开始时间晚于上一个的话,就可以看这一个节目,然后结束时间需要更新成这一个节目的结束时间。
#include<iostream>
#include <deque>
#include<stack>
#include<queue>
#include<math.h>
#include<algorithm>
#include<stdlib.h>
#include<string>
#include<stdio.h>
#include<string.h>
typedef long long LL;
#define $ 3.141592654
using namespace std;
struct W
{
int a,b;
};
bool cmp(struct W x,struct W y)
{
return x.b<y.b;
}
int main()
{
for(;;)
{
int n,i,j=1,k;
struct W w[100];
scanf("%d",&n);
if(n==0)
break;
for(i=0;i<n;i++)
scanf("%d%d",&w[i].a,&w[i].b);
sort(w,w+n,cmp);
k=w[0].b;
for(i=1;i<n;i++)
{
if(w[i].a<k)
continue;
else
{
j++;
k=w[i].b;
}
}
printf("%d\n",j);
}
return 0;
}
贪心最重要的一点就是“贪”,贪就是尽可能的获取一个最优的解,做题时首先要思考如何实现最优解。