引言
事先聲明,我學習貪心算法之前只是理解了動態規划的裝配線調度問題,其它的動態規划基礎基本為零,我感覺很多問題都可以用貪心來解決,因此在這里總結一下我學習貪心算法的過程,很多東西是靠做題和死記硬背理解的,唉,為自己的智商着急啊!
我采用通過acm題的方式來分析一下我理解的貪心算法!
例題
題目描述: 又到畢業季,很多大公司來學校招聘,招聘會分散在不同時間段,小明想知道自己最多能完整的參加多少個招聘會(參加一個招聘會的時候不能中斷或離開)。 輸入: 第一行n,有n個招聘會,接下來n行每行兩個整數表示起止時間,由從招聘會第一天0點開始的小時數表示。 n <= 1000 。 輸出: 最多參加的招聘會個數。 樣例輸入: 3 9 10 10 20 8 15 樣例輸出: 2
活動選擇問題
概述
這個問題是對幾個相互競爭的招聘會活動進行調度,它們都要求以獨占的方式使用某一公共資源(小明)。調度的目標是找出一個最大的相互兼容的活動集合。這里是有一個需要使用某一資源(小明)的n個活動組成的集合S={a1,a2,...,an}.該資源一次只能被一個活動占用。每個活動ai有開始時間si和結束時間fi,且0<=si<fi<無窮。一旦被選擇后,活動ai就占據了區間[si,fi].如果區間[si,fi]和[sj,fj]互不重疊,稱活動ai和aj是兼容的。活動選擇問題就是要選擇出一個由互相兼容的問題組成的最大子集合。
將所有的活動按照結束時間升序排列
i | 1 | 2 | 3 |
si | 9 | 8 | 10 |
fi | 10 | 15 | 20 |
定理
對於任意非空子問題Sij,設am是Sij中具有最早結束時間的活動:
fm=min{fk:ak屬於Sij}
那么,
1)活動am在Sij的某最大兼容活動子集中被使用
2)子問題Sim為空,所以選擇am將使子問題Smj為唯一可能非空的子問題
ac代碼
#include <stdio.h> #include <stdlib.h> #include <string.h> struct join { int begin; int end; }; int compare(const void *a, const void *b); int main() { int i, n, k; struct join joins[1001], temp[1001]; while(scanf("%d", &n) != EOF) { for(i = 0; i < n; i ++) { scanf("%d %d", &joins[i].begin, &joins[i].end); } qsort(joins, n, sizeof(joins[0]), compare); k = 0; temp[k] = joins[0]; for(i = 1; i < n; i ++) { if(joins[i].begin >= temp[k].end) temp[++ k] = joins[i]; } printf("%d\n", k + 1); } return 0; } int compare(const void *a, const void *b) { const struct join *p = a; const struct join *q = b; return p->end - q->end; } /************************************************************** Problem: 1463 User: wangzhengyi Language: C Result: Accepted Time:10 ms Memory:904 kb ****************************************************************/