/* 题目:尽可能看多的电视节目,时间为整点 输入: 第一行一个整数n为喜欢看电视的节目总数,下面有n行数据,每一行数据包含2个数据Ti_s,Ti_e表示第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 排序: 下标:0 1 2 3 4 5 6 7 8 9 10 11 1 3, 3 4, 0 7, 3 8, 2 9, 5 10, 6 12, 4 14, 10 15,` 8 18, 15 19, 15 20 选择 选择 选择 选择 选择 选择 选择 选择 选择 选择(第一趟),确定1 3,3 4 j=0 选择 选择 选择 选择 选择 选择 选择 选择 选择(第二趟) ,确定1 3, 3 4,5 10 j=1 选择 选择 选择 选择 选择 选择(第三趟),确定1 3, 3 4,5 10,10 15 j=5 选择 选择 选择 选择 选择 (第四趟),确定1 3, 3 4,5 10,10 15,15 19 j=8 j=10 输出: 5 思路:尽可能选择时间跨度范围小的,并且一个节目的结束时间要小于另一个节目的开始时间。思路错误 应该优先选择结束时间最早的,最优解是结束时间最早。假设第一个节目A[s1,e1],有比A更早结束的节目B,那么用 B替换A不影响A后面节目顺序,因此这也是最优解。 所以当第x-1个节目选择结束后,选择剩余节目中最早结束的节目 贪心算法: 1要证明 2用反证 关键: 1 通过设置标记法,来做过滤,已经过滤掉的,下次循环不做处理 2 设置下一个节目下标时,初始值设为iMinIndex=iNum,以防止最后一次一直拿不到iMinIndex时,程序能够退出循环 3 bool operator < (const Show& show) const//常成员修饰符不能丢,否则报大量stl错误 方法2: 在遍历的过程中,只需搜索一遍,起初设置curTime = 0,然后另curTime<=show[i].endTime,然后不断更新curTime即可 */ #include <stdio.h> #include <stdlib.h> #include <memory.h> #define MaxSize 100 typedef struct Show{ bool operator < (const Show& show) const//常成员修饰符不能丢,否则报大量stl错误 { return uEndTime < show.uEndTime; } unsigned uBegTime; unsigned uEndTime; bool isDel;//删除标记,初始均设为false,一旦确定上一个节目后,下一个节目从剩余节目中选择,如果showA.uEndTime > showB.uBegTime,就设这个节目的isDel=true; }Show; int partition(Show* show,int low,int high) { Show iPos = show[low]; while(low < high) { while( low < high && iPos < show[high]) { high--; } show[low] = show[high]; while( low < high && show[low] < iPos) { low++; } show[high] = show[low]; } show[low] = iPos; return low; } void quickSort(Show* show,int low,int high) { if(low < high) { int iPos = partition(show,low,high); quickSort(show,low,iPos-1); quickSort(show,iPos+1,high); } } int main() { int iNum; Show show[MaxSize]; while(EOF!=scanf("%d",&iNum) && iNum > 0) { for(int i = 0;i < iNum ; i++) { scanf("%d %d",&show[i].uBegTime,&show[i].uEndTime); if(show[i].uBegTime < 0 || show[i].uBegTime > 24 || show[i].uEndTime < 0 || show[i].uEndTime > 24) { printf("The time you input is not valid!\n"); } } quickSort(show,0,iNum-1); unsigned curTime = 0; int iCount = 0; for(int j = 0 ; j < iNum ;j++) { if(curTime <= show[j].uBegTime) { curTime = show[j].uEndTime; iCount++; } } printf("%d\n",iCount); } system("pause"); getchar(); return 0; } /* int main(int argc,char* argv[]) { int iNum; Show show[100]; //获取输入 while(EOF!=scanf("%d",&iNum) && iNum >0 && iNum <= 24) { //printf("%d\n",iNum); for(int i = 0 ; i < iNum ; i++) { scanf("%d %d",&show[i].uBegTime,&show[i].uEndTime); if(show[i].uBegTime < 0 || show[i].uBegTime > 24 || show[i].uEndTime < 0 || show[i].uEndTime > 24) { printf("The time you input is not valid!\n"); return -1; } show[i].isDel = false; } //开始进行贪心算法:2个条件,第i个节目的结束时间一定是最小的,剩下待选节目需要通过 当前节目开始时间 < 上一个节目结束时间,来过滤 //先按照节目结束时间早到晚进行快速排序,这样第一个节目的结束时间一定是最早的 quickSort(show,0,iNum-1); int j,k; int iCount = 0;//能看多少节目的计数器 for(j = 0; j < iNum ; ) { int iMinIndex = iNum;//设置false的最小下标,易错,若不设置为iNum,永远退出不了循环 iCount++;//j每次能重新遍历,说明是从当前节目开始的 bool isFirst = true;//第一次进入的标记 for(k = j + 1; k < iNum ;k++) { //易错,之前已经过滤的必须直接过滤掉 if(true==show[k].isDel) { continue; } if(show[j].uEndTime > show[k].uBegTime) { show[k].isDel = true; } else { //确定下一个符合节目最小下标是多少,并且令j从新的节目开始,进行循环 if(true==isFirst) { iMinIndex = k;//最后一次为10 isFirst = false; } } } //等到整个循环遍历结束,对j进行重新赋值为iMinIndex,如果最后一次一直没有找到需要特殊处理 j = iMinIndex; }//for printf("%d\n",iCount); } system("pause"); getchar(); return 0; } */