解决方案 »

  1.   

    而所谓的截枝,应该是在每一步的填充后都校验一下
    比如刚刚排到第一天,就发现某个老师连续上了6节数学课,那赶紧把这个方案丢弃吧,而不是等周五都排好了才发现这个大BUG
      

  2.   

    我现在的基本思路是这样的,填写如下表格我把9门课的老师,放入9个不同的队列(开始用栈),每个队列里都是教同一门课的老师,队列元素是结构体,Struct Teacher{教师ID,学科名1,学科名2,代课累计计算器},算法按列填表,填满第一列后再填写第2,……6列,这样可以保证时间上没有冲突。for(int Col=0;Col<6;Col++)
    {
      for(int RowIndex=0;RowIndex<16;RowIndex++)
      {
          //取队列,以便从中找出一个老师填写单元格
          if(Col>=3)//若语数外没排上,则最后三节考虑排
          {
             从当前单元格沿着行向左方探索,查找语数外情况
              if(语数外没排上)  //或其中2个或1个没排上
             {
                 从语数外三科(或2科或1科)的队列里,任取一个队列;            }
              else
             {
                 从除去语数外(或2科或1科)的队列里,任取一个队列;
             }       }
           else
           {
               从9个队列中任意取一个队列;
           }
           
           当前队列出队,读取当前老师对应的学科;
           沿着行向左探索,查找该学科是否已经排过;  //同一个班,一天内,一门课,只上一次
            if(该学科没有排过 && 该老师累计上课不超过3次)
            {
              填写当前单元格;
              填写过的老师,入队,排到队尾,以便再次排课;
           }
           else
           {
              重选队列;
           }     }
    }不知道说明白了没。这样保证了一天一个班某一门课最多上一节,但是,尽管取学科的时候,是用随机数实现的,但最后三节,有时候限制了只能在语数外里取,导致语数外排在最后三节的多,这样做是为了减少调整的次数,为在一周内调整赢得时间,提高点效率。(1)大家看我这种算法,还有继续改进的价值吗?
    (2)要是还有价值,那么接下来一周内的调整怎么做,把5天的结果放到5个datatable,检查除了语数外的6门课,一周内总和是不是都是2节,不都是,要调整,是重排5天所有的课,还是只重排某几天的就行?还是看情况:先调整星期五的,若无解,则调整星期四和星期五2天的,……,直到都调整了,期间,找到解就退出