算法导论学习笔记(十四):贪心算法(一):活动安排问题

来源:互联网 发布:成濑川奈留 知乎 编辑:程序博客网 时间:2024/05/21 16:48

对很多最优化问题来说,采用动态规划方法来解决就有点大材小用了。有时候我们可以采用贪心算法来取代。贪心算

是通过所做的局部最佳选择来产生一个全局最优解。而且和动态规划不同的是,它是通过自顶向下的方式来解决每

一个子问题。而活动安排问题可以说是贪心算法的一个入门学习。


当我看到这个问题时,首先就想到了自己大一做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;}



原创粉丝点击