核心思想:贪心算法
都说贪心算法是求局部最优解,那么首先要找到局部。
而在本题情境中的局部是“如何选择节目”,
更细一点分为“如何选第一个节目”和如何选“第n个节目的下一个节目”。
讨论:这里你理解我想表达的了吗?上述分析已经完成了贪心算法中“将问题拆分成若干个子问题”的步骤了!后面就可以对这些“子问题”求解了,即局部最优解。我认为值得关注的一些点:拆解的子问题要具有相同的“结构”,比如说可能是可递推性,因为这样子问题才能被同样的办法求解,从而实现问题简化而后办法易显,毕竟用贪心就是因为整体问题复杂难找办法才用的。
然后继续本题的思考。
如何选第一个节目呢?先看看我们掌握什么信息,我们知道每个节目的开始时间,还知道每个节目的结束时间,那么都研究一下这两个信息吧。正常人思维,想看更多的节目,这节目得看得早会方便看下一个节目或者结束得早方便看下一个节目嘛,但是开始得早结束不一定早,而结束得早,开始得也早因为开始比结束要早嘛,于是初步先尝试性地把目光放在结束时间,选最早结束的作为第一个节目。
而第二个节目怎么选呢?首先应该要晚于第一个节目开始,然后重复上述思考,同样得出选相对于第一个节目最早结束的节目为局部最佳解。第n个节目以此类推。
代码部分(带分析)
#include <stdio.h>
struct se
{
int s;
int e;
}program[101];
int main(){
int n;
int i;
int i1;
int tmp;
int cot;
while (scanf("%d",&n)!=EOF && n!=0)
{
for ( i = 0; i < n ; i++)
{
scanf("%d %d",&program[i].s,&program[i].e);
}
for ( i = 0; i < n-1 ; i++)//冒泡排序,得到递增数列
{
for ( i1 = 0; i1 < n-1-i ; i1++)
{
if (program[i1].e>program[i1+1].e)//比较结束的早晚
{
program[101]=program[i1];
program[i1]=program[i1+1];
program[i1+1]=program[101];
}
}
}
tmp=0;//先存取最早结束的下标
cot=1;//最早结束的看了,故计数从一开始
for ( i = 0; i < n ; i++)
{
//printf("%d %d\n",program[i].s,program[i].e);
if(program[i].s>=program[tmp].e)
{
tmp=i;
cot++;
i=0;//因为每确定一个节目,都要继续找其后一个节目,故重置循环,再次开始寻找
}
}
printf("%d\n",cot);
}
return 0;
}