• 算法导论16.13 区间图着色(intervalgraph 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
  • 相关阅读:
    Discuz利用百度ping把我们网站自动提交到百度
    正则表达式速查表1
    thinkphp 新浪新闻采集代码演示
    php采集一网站的精美图片
    百度知道的php爬虫
    新浪新闻采集程序
    mysql pid文件丢失解决办法
    js位运算-按位非
    mysql表损坏解决方案
    h5新API之WebStorage解决页面数据通信问题
  • 原文地址:https://www.cnblogs.com/null00/p/2499863.html
Copyright © 2020-2023  润新知