算法导论16.1-3 区间图着色(interval-graph coloring)问题(贪心算法)

CLRS 16.1-3 假设要用很多个教室对一组活动进行调度。我们希望使用尽可能少的教室来调度所有的活动。请给出一个有效的贪心算法,来确定哪一个活动应使用哪一个教室。

(这个问题也被成为区间图着色(interval-graph coloring)问题。我们可作出一个区间图,其顶点为已知的活动,其边连接着不兼容的活动。为使任两个相邻结点的颜色均不相同,所需的最少颜色对应于找出调度给定的所有活动所需的最少教室数。)

方法一:
我们很容易就可以想到用P227页的GREEDY-ACTIVITY-SELECTOR(s, f)来解决这个问题,首先调用这个函数,得到可以兼容的最大活动数,然后再在余下的活动中再次调用这个函数,直至活动为0。 见代码清单-1

方法二:
1.对于所有活动的时间点按升序进行排序(n个活动,就有2n个时间点),记录每个时间是起始的还是终止的,在排序的时候,对于值相同的时间点,如果是终止时间点的话,就排在前面。
2.最开始,选择第一个起始时间点,把它对应的活动放入一个教室,同时记录这个起始时间点对应的终止时间点。
3.接着按序选择第i个起始时间点(只选择起始时间点),对于第i个起始时间点,比较它和已有教室中的活动的终止时间点,若大于某个终止时间点,则直接将第i个起始时间点对应的活动放进相应的教室,否则新开辟一个教室来放入这个活动。 见代码清单-2

对于区间图着色(interval-graph coloring)问题,先在一个集合中放入一个点,然后把不与这个点相邻的所有元素放入这个集合,对于剩下的点,重复前面的动作即可,依此循环,直至没有点可选。最后,有多少个集合就是多少种颜色,集合中的元素用相同的色渲染。

代码清单-1:

View Code
 1 #include <stdio.h>

 2 #include <stdlib.h>

 3 

 4 //活动

 5 typedef struct activity_t

 6 {

 7   int start;//起始时间

 8   int end;//结束时间

 9 } activity;

10 

11 //和P227页的算法思路相同

12 void greedy_algorithm(activity* data, const int n)

13 {

14   if (n > 0)

15   {

16     int sequence[n];

17     int i;

18     for (i = 0; i < n; i++)

19       sequence[i] = -1;

20     i = 0;

21     sequence[i] = 0;

22     int count = 0;

23     int tmp = 0;

24     while ((++count) < n)

25       {

26     if (data[count].start >= data[tmp].end)

27       {

28         sequence[++i] = count;

29         tmp = count;

30       }

31       }

32     int j;

33     for (j = 0; j < n; j++)

34       {

35     if (sequence[j] == -1)

36       break;

37     printf("[%d,%d)\t", data[sequence[j]].start, data[sequence[j]].end);

38       }

39     printf("\n----------\n");

40 

41     //对于剩下的数据再调用本函数

42     activity* remain_data = (activity*)malloc(sizeof(activity)*(n-j));

43     int p;

44     int q;

45     int k = 0;

46     for (p = 0; p < n; p++)

47       {

48     int flag = 0;

49     for (q = 0; q < j; q++)

50       {

51         if (p == sequence[q])

52           {

53         flag = 1;

54         break;

55           }

56       }

57     if (flag == 0)

58       {

59         remain_data[k++] = data[p];

60       }

61       }

62     greedy_algorithm(remain_data, n-j);

63     free(remain_data);

64   }

65 }

66 

67 int main()

68 {

69   int n;

70   scanf("%d", &n);

71   activity* data = (activity*)malloc(n*sizeof(activity));

72   activity a;

73   int rows = n;

74   //按照结束时间从小到大进行输入,P222页底下表格中的数据

75   while (rows--)

76   {

77     scanf("%d%d", &(a.start), &(a.end));

78     data[n-rows-1] = a;

79   }

80   greedy_algorithm(data, n);

81   free(data);

82   return 0;

83 }

代码清单-2:

View Code
 1 #include <stdio.h>

 2 #include <stdlib.h>

 3 

 4 //每个时间点;是起始时间,还是终止时间;及其对应的结束时间

 5 typedef struct point_t

 6 {

 7   int time;

 8   int is_start;

 9   int end_time;//若is_start为1,end_time写对应的时间;若is_start为0,end_time为-1

10 } point;

11 

12 //升序排列,若时间相同,则为终止时间的时间点排在前面

13 int compare(const void* a, const void* b)

14 {

15   if ((*(point*)a).time != (*(point*)b).time)

16     return (*(point*)a).time > (*(point*)b).time;

17   else 

18     return (*(point*)a).is_start < (*(point*)b).is_start;//这里得用小于

19 }

20 

21 void process(point* points, const int n)

22 {

23   //排序

24   qsort(points, n, sizeof(point), compare);

25   //最多n/2个教室

26   int classrooms[n/2];

27   int count = 0;

28   classrooms[count++] = points[0].end_time;

29   printf("[%d, %d)在教室%d\n", points[0].time, points[0].end_time, count);

30   int i;

31   int j;

32   for (i = 1; i < n; i++)

33   {

34     if (points[i].is_start == 1)

35     {

36       for (j = 0; j < count; j++)

37       {

38     if (classrooms[j] <= points[i].time)

39     {

40       classrooms[j] = points[i].end_time;

41       printf("[%d, %d)在教室%d\n", points[i].time, points[i].end_time, j+1);

42       break;

43     }

44       }

45       if (j == count)

46       {

47     classrooms[count++] = points[i].end_time;

48     printf("[%d, %d)在教室%d\n", points[i].time, points[i].end_time, count);

49       }

50     }

51   }

52   printf("总共需要%d个教室.\n", count);

53 }

54 

55 int main()

56 {

57   int rows;

58   scanf("%d", &rows);

59   //2*rows个点

60   point* points = (point*)malloc(2*rows*sizeof(point));

61   //point p;

62   int n = rows;

63   //point p;

64   int start_time;

65   int end_time;

66   while (rows--)

67   {

68     int id = n - rows - 1;

69     scanf("%d%d", &start_time, &end_time);

70     point p1;

71     p1.is_start = 1;

72     p1.time = start_time;

73     p1.end_time = end_time;

74     points[2*id] = p1;    

75     

76     point p2;

77     p2.is_start = 0;

78     p2.time = end_time;

79     p2.end_time = -1;

80     points[2*id + 1] = p2;

81   }

82   process(points, 2*n);

83   free(points);

84   return 0;

85 }

输入数据为:

11

1 4

3 5

0 6

5 7

3 8

5 9

6 10

8 11

8 12

2 13

12 14

你可能感兴趣的:(color)