问题描述 “今年暑假不学习?” “是吗?那你打算干什么呢?” “看电视剧呀!” “那么多电视剧你看得完吗?” "对哦,那是的好好安排一下节目了。"
确实如此,暑假来了,假期档的电视剧也来了,估计很多电视迷会抛开学业,奔向电视。 作为电视迷,一定想看在一天内看尽量多的完整的电视剧。当然,作为新时代的好青年,你一定还会看一些其它的节目,比如新闻联播(永远不要忘记关心国家大事)、流淌的美好时光、长安十二时辰、陈情令,以及王小丫的《开心辞典》等等,假设你已经知道了所有你喜欢看的电视节目的转播时间表,你会合理安排吗?(目标是能看尽量多的完整节目) 输入 输入数据包含多个测试实例,每个测试实例的第一行只有一个整数n(n<=100),表示你喜欢看的节目的总数,然后是n行数据,每行包括两个数据Ti_s,Ti_e (1<=i<=n),分别表示第i个节目的开始和结束时间,为了简化问题,每个时间都用一个正整数表示。n=0表示输入结束,不做处理。 输出 对于每个测试实例,输出能完整看到的电视节目的个数,每个测试实例的输出占一行。 样例输入 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 样例输出 5
解题思路
即为给出一个总长度确定的区间,再输入不同的子区间,求在这个总区间里面包含的不相交的子区间最多有多少个。
可以由最特殊的情况来想,即给出的这些子区间现在都不相交,比如
----- (1,3) 1
---------- (2,4) 2
--------(5,7) 3
-----------------(8,10) 4
可以看到在0到10这个总的区间里面,一共有max=4个不相交的子区间,则从特殊到一般,如果我们将区间4向左移动,那么不相交的子区间的数目max变为3,就减少了1个,同理可得,如果移动其他子区间,都会导致max的值变小(该区间的移动导致它和另一个子区间相交)或者不变(该区间的移动不会导致与其他区间相交),则我们可以得出一般情况下最优解的情况就应该是类似最特殊的这种情况的形式。即最优解的情况应为,第二个子区间的起点大于第一个子区间的终点(用这个作为判断条件来遍历即可),这样保证它们是没有交点的,所以就要求这些子区间是有序的,将它们按照终点的从小到大的排序,可以从上述例子得到终点最小的区间一定是包含在最优解里面的,(因为它结束最晚,开始最早,一定排在经过排序后的区间的最左端)。
#include<stdio.h> struct Time { int Ti_s; //开始时间 int Ti_e; //结束时间 }; int main() { int a,i,j,count; Time time[100],temp; //电视节目总数,结构体来表示 while(scanf("%d",&a)!=EOF&&a!=0) { for(i=0;i<a;i++) scanf("%d%d",&time[i].Ti_s,&time[i].Ti_e); //按照结束时间从小到大对节目进行排序 for(i=0;i<a;i++) for(j=i+1;j<a;j++) { if(time[i].Ti_e > time[j].Ti_e || (time[i].Ti_e == time[j].Ti_e && time[i].Ti_s > time[j].Ti_s ) ) { temp = time[i]; time[i] = time[j]; time[j] = temp; }//temp结构体它的开始时间保存着上一个节目的结束时间 } for(i=1,j=0,count=1;i<a;i++) { if(time[i].Ti_s>=time[j].Ti_e) { count++; j=i; } }//贪心算法,排序后的第一个节目肯定要看,然后依次计算下一个节目的开始时间大于等于上一个节目的结束时间的节目数 printf("%d\n",count); } return 0; }View Code