ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
123
返回列表 发新帖
楼主: excelw

[求助] 请高手指教——按要求分班

[复制链接]

TA的精华主题

TA的得分主题

发表于 2012-7-25 16:13 | 显示全部楼层
本帖最后由 灰袍法师 于 2012-7-26 19:51 编辑
ex121 发表于 2012-7-25 15:07
法师的基本思路是怎样的啊?
能介绍一下吗?
谢谢!

简单注释一下关键代码,基本的算法就是二楼 DataBus 说的随机分
不过具体做法是:前50%的学生随机分配,这样会导致每班学生人数不一样
所以后50%的学生直接分配到人数最少的班
重要的是对分配方案的评估函数,这里用的是所有科目的分差的平方和最低
For k = 1 To loop_times

清空每个物品分配到哪个容器的记录 plan(1 to item_count)
清空每个容器的人数记录 plan_rec(1 to item_count)

ReDim plan(1 To item_count)
ReDim pack_rec(1 To pack_count)

For i = 1 To item_count

        对于所有的待分配物品,如果属于前50%,随机分配到某个容器
    If i <= 0.5 * item_count Then
        pos = Int(Rnd * pack_count) + 1

        对于所有的待分配物品,如果属于后50%,分配到人数最少的那个容器,以保持每个班人数平衡
    Else
        min_pack = pack_rec(1)
        pos = 1
        For j = 2 To pack_count
            If pack_rec(j) < min_pack Then
                min_pack = pack_rec(j)
                pos = j
            End If
        Next j
    End If

    分配方案的第i个人,分配到第 pos 个班,该班的人数记录+1
    plan(i) = pos
    pack_rec(pos) = pack_rec(pos) + 1
Next i

这里是最关键的部分,对分配好的方案 plan(),进行评估,给出一个分数
Call Evaluate(plan, result)

如果分数比之前的分配方案更好,就保留。
If result < best_result Then
    best_result = result
    best_plan = plan
End If
Next k

评估函数
Sub Evaluate(plan() As Long, result)
Dim p As Long, q As Long, pos As Long, key As Long
Dim count(), avg(), total()

记录每个科目的总分,平均分,人数的数组
ReDim total(1 To pack_count, 1 To key_count)
ReDim avg(1 To pack_count, 1 To key_count)
ReDim count(1 To pack_count)

计算总分和人数
For p = 1 To item_count
    pos = plan(p)
    count(pos) = count(pos) + 1
    For q = 1 To key_count
        total(pos, q) = total(pos, q) + data(p, q)
    Next q
Next p

计算平均分
For p = 1 To pack_count
    For q = 1 To key_count
        avg(p, q) = total(p, q) / count(p)
    Next q
Next p

求出每个科目的班最低平均分,最高平均分
ReDim max_avg(1 To key_count)
ReDim min_avg(1 To key_count)
For p = 1 To key_count
    max_avg(p) = avg(1, p)
    min_avg(p) = avg(1, p)
Next p

For p = 1 To key_count
    For q = 2 To pack_count
        If avg(q, p) > max_avg(p) Then max_avg(p) = avg(q, p)
        If avg(q, p) < min_avg(p) Then min_avg(p) = avg(q, p)
    Next q
Next p

打分了。。。
这里的评判标准很简单,每个科目的最高平均分 - 最低平均分,取平方和
然后把每个科目的这个平方和结果加起来
作为分配方案的最终分数(即要求每个科目的分差越低越好)
你可以给出各种不同的评估标准
如要求 总分的分差越低越好,就可以给总分的分差平方和乘以一个权重,如 x10
这样得到的最佳分班,将会有个比较低的总分分差,但是某一单科分差可能会比较高

result = 0
For p = 1 To key_count
    result = result + (max_avg(p) - min_avg(p)) ^ 2
Next p
这里补一句给最后一项科目的分差的平方和,多10倍的权重,求出的总分平均分结果更好!
    result = result + 10 * (max_avg(key_count) - min_avg(key_count)) ^ 2

End Sub




TA的精华主题

TA的得分主题

发表于 2012-7-25 16:30 | 显示全部楼层
灰袍法师 发表于 2012-7-25 16:13
简单注释一下关键代码,基本的算法就是二楼 DataBus 说的随机分
不过具体做法是:前50%的学生随机分配, ...

法师真乃神人也.
我再修行几辈子也望尘莫及呵.

TA的精华主题

TA的得分主题

发表于 2012-7-26 09:24 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
excelw 发表于 2012-7-24 07:56

我给你做的那个分班难道不好用吗,貌似每个班分的成绩都是差不多的呢,就是要收工把男、女生分成两个表而已,剩下的六个人男女不能平均分配了,只能人工调整了,这个分班到最后都得这样,你不要想一个公式能解决你的问题,那样是很难实现的,除非男、女生人数刚刚好能分6个班

TA的精华主题

TA的得分主题

发表于 2012-7-26 19:21 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
本帖最后由 灰袍法师 于 2012-7-26 19:57 编辑

17楼补充了一个分批次分班的方法,可以解决随机算法求解精度不高的毛病
方法是缩减每次分班的规模,从而得到更高的精度和求解速度。
当然,对于极大数量的学生和班级数,这个方法也是不中用的
如分5000学生到100个班。。。。。。

TA的精华主题

TA的得分主题

发表于 2014-8-4 07:53 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
灰袍法师 发表于 2012-7-24 19:51
附件是最无脑的随机分班法,设定更多的随机次数可以获得更好的结果
学生数班数越多,效果越差;学生数班数 ...

多次分班,好!思路愈加宽广了……

TA的精华主题

TA的得分主题

发表于 2018-8-29 07:32 | 显示全部楼层
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-11-16 19:28 , Processed in 0.046287 second(s), 8 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表