对很多最优化问题来说,采用动态规划方法来解决就有点大材小用了。有时候我们可以采用贪心算法来取代。贪心算
法是通过所做的局部最佳选择来产生一个全局最优解。而且和动态规划不同的是,它是通过自顶向下的方式来解决每
一个子问题。而活动安排问题可以说是贪心算法的一个入门学习。
当我看到这个问题时,首先就想到了自己大一做ACM时在杭电acm里遇到的一个题目:今年暑假不AC。可以说这个题
目就是活动安排问题的翻版,只是一个讲的是怎么安排最多活动,一个讲的是最多能看到的电视节目。但本质是一样
的。下面我就以今年暑假不AC这道题目来说明吧。
当时看到这道题的时候想的是排序,然后暴力找。开始是按开始时间排序的,结果发现这样做没什么意义。因为有的
节目开始很早,但可能是最晚一个接受的,这样的话不能保证能得出最大值。于是便以结束时间来排序,毫无疑问,
排在最前面的那个肯定可以看,然后以这个为基础,从后依次遍历,找到第一个开始时间大于这个结束时间的节目,
并将这个节目在数组中的下标i做一个标记,并设k = i,然后从这个节目开始继续往后遍历,找出第一个节目j,使
a[j].start >= a[k].end。然后设k = j,继续往后遍历。依此循环下去,直到遍历完所有节目。实现代码如下:
#include<stdio.h> struct Node { int s; int e; }; int main() { int n; int i, j, k; int count; Node a[100], temp; while (scanf("%d", &n), n) { for (i = 0; i < n; i++) { scanf("%d%d", &a[i].s, &a[i].e); } for (i = 0; i < n - 1; i++) { for (j = 0; j < n - i - 1; j++) { if (a[j].e > a[j + 1].e) { temp = a[j]; a[j] = a[j + 1]; a[j + 1] = temp; } } } count = 1; k = 0; for (i = 1; i < n; i++) { if (a[i].s >= a[k].e) { k = i; //标记选中的节目 count++; } } printf("%d\n", count); } return 0; }
#include<stdio.h> struct Node { int s; int e; }; int count; void fun (Node a[], int i, int n) { int m = i + 1; while ((m <= n) && (a[i].e > a[m].s)) m++; if (m <= n) { count++; fun (a, m, n); } } int main() { int n; int i, j; Node a[100], temp; while (scanf("%d", &n), n) { for (i = 0; i < n; i++) { scanf("%d%d", &a[i].s, &a[i].e); } for (i = 0; i < n - 1; i++) { for (j = 0; j < n - i - 1; j++) { if (a[j].e > a[j + 1].e) { temp = a[j]; a[j] = a[j + 1]; a[j + 1] = temp; } } } count = 1; fun(a, 0, n-1); printf("%d\n", count); } return 0; }