Algorithm 按姓氏把人分成几个房间?
我经常教大型的编程入门课程(400-600名学生),当考试时间到来时,我们常常不得不将课程分成不同的教室,以确保每个人都有座位参加考试 为了保持逻辑上的简单,我通常按姓氏将类分开。例如,我可能会把姓A-H的学生送到一个房间,姓I-L的学生送到第二个房间,姓M-S的学生送到第三个房间,姓T-Z的学生送到第四个房间 这样做的挑战是,教室的容量往往相差悬殊,很难找到一种方法来划分班级,使每个人都能适应。例如,为简单起见,假设姓氏的分布如下:Algorithm 按姓氏把人分成几个房间?,algorithm,Algorithm,我经常教大型的编程入门课程(400-600名学生),当考试时间到来时,我们常常不得不将课程分成不同的教室,以确保每个人都有座位参加考试 为了保持逻辑上的简单,我通常按姓氏将类分开。例如,我可能会把姓A-H的学生送到一个房间,姓I-L的学生送到第二个房间,姓M-S的学生送到第三个房间,姓T-Z的学生送到第四个房间 这样做的挑战是,教室的容量往往相差悬殊,很难找到一种方法来划分班级,使每个人都能适应。例如,为简单起见,假设姓氏的分布如下: 姓氏以A:25开头 姓氏以B:150开头 姓氏以C:200
- 姓氏以A:25开头
- 姓氏以B:150开头
- 姓氏以C:200开头
- 姓氏以D:50开头
- 每个房间最多应分配一块连续的字母,以及
- 不得将任何信件分配给两个或多个房间
谢谢 这个问题是
NP完全的
,因此没有已知的多项式
时间(也称有效)解决方案(只要人们不能证明p=NP
)。您可以将背包或箱子包装问题的实例简化为您的问题,以证明它是NP完全的
要解决这个问题,你可以使用0-1背包问题。以下是如何:
首先选择最大的教室大小,并尝试分配尽可能多的学生组(使用0-1个背包),即与房间大小相等。你保证不会分裂一组学生,因为这是0-1背包。完成后,到下一个最大的教室继续上课
(您可以使用任何已知的启发式方法来解决0-1背包问题。)
这是降价单--
您需要将0-1背包的一般实例简化为问题的特定实例。
让我们来举一个0-1背包的一般例子。让我们拿一个重量为W
的袋子,你有x_1,x_2。。。x_n
组及其相应的权重为w_1,w_2。。。w_n
现在简化——这个一般实例简化为您的问题,如下所示:
您有一间可容纳座位的教室W
。每个x_i(i\in(1,n))
是一组学生,他们的最后一个字母表以i
开头,他们的数字(也称为组大小)是w_i
现在你可以证明,如果0-1背包问题有解,你的问题有解……反之亦然……如果0-1背包没有解,那么你的问题就没有解,反之亦然
请记住简化的重要内容——将已知
NP-C
问题的一般实例简化为您的问题的特定实例
希望这有帮助:)可以在
[m,2^n]
空间中使用某种DP解决方案来解决,其中m
是字母数(英文为26),而n
是房间数。使用m==26
和n==20
将需要大约100MB的空间和约1秒的时间。
下面是我刚在C语言中实现的解决方案(它将成功地在C++和java上编译,只需要几个小的改动):
int[]GetAssignments(int[]studentsPerLetter,int[]rooms)
{
int numberOfRooms=房间长度;
int numberOfLetters=studentsPerLetter.Length;
int roomset=1=0&&roomCapacity>=studentsPerLetter[lastIndex];lastIndex--)
{
res[lastIndex]=lastRoom;
房间容量-=学生人数[lastIndex];
}
roomMask^=1-1?空值:res;
}
OP问题示例:
答案是:
2
0
0
1
表示每个学生姓氏字母的房间索引。如果无法分配,我的解决方案将返回null
[编辑] 在数千次自动生成的测试之后,我的朋友发现代码中有一个错误,它会反向构造解决方案。它不会影响主算法,因此修复此错误将是读者的一项练习 揭示错误的测试用例是
students=[
2
0
0
1