在编程之美中,有一道高效安排见面会的问题
问题描述如下
已知有n位学生,他们分别对M个研究项目中的若干个干兴趣,每个见面会的时间为T,每个学生都能参加自己感兴趣的所有见面会,如何安排时间总时间最短??
编程之美的解法
把该问题转化成图染色的问题,
每个见面会为一个点,如果有个同学对其中两个见面会感兴趣,那么这两点就有一天联系,
染色问题:就是如果两个点之间有连线,那么他们要用不同的颜色染色,问最少用多少颜色给这个图染色。
这个问题的解法复杂度高,同时编程实现起来也难,复杂度为O((N-1)nN2)
比较优的解法:
1.T[M],表示第i个时间断,安排了那些见面会;初始化,把所有的见面 会放在第一个时间段T[0]。
2.WATCH[M],每个见面会被关注的次数,初始化WATCH,为T[0]中的见面会,被关注的次数。
init T[M];
init Watch[m];
count=0;
while(there is Watch[i]>1) /*有一个见面被关注次数大于1*/
{
while((location=max_in_watch_location(Watch))>1) /*按照关注次数高低,把关注次数超1依次移动到下一个时间段T[count++];*/
{
remove_next(T,count,location) /*把T[count]中的见面会编号为locaiton 移动到T[count+1] */
Watch[location]=0
}
count++;
用T[count],重新计算Watch[M] //T[count]中的见面会背关注的次数
}
大概思想如上,可以看出是实现起来很见到,现在我们在计算复查度
每次计Watch[M],次数为O(NM)
把不能安排在一起的讨论会移动到下一个时间段复杂度 : O(M log(M))
所以时间复杂度为 O(NM2 log(M))